From c9bf3b91fe8c993a296599be8e89bacaff8eb7e5 Mon Sep 17 00:00:00 2001 From: Nikolay Nikolaev Date: Sun, 15 Dec 2019 23:10:48 +0200 Subject: [PATCH] Initial implementation of OMEC/NGIC SPGW example This includes a basic deplyment and a manual start of the DP. Signed-off-by: Nikolay Nikolaev --- examples/4g-spgw/Makefile | 49 +++++ examples/4g-spgw/README.md | 37 ++++ examples/4g-spgw/dp-init/Dockerfile | 4 + examples/4g-spgw/dp-init/setup_af_packet.sh | 20 ++ examples/4g-spgw/enb-sim/Dockerfile | 17 ++ examples/4g-spgw/k8s/4g-network.yaml | 29 +++ examples/4g-spgw/k8s/enb-sim.yaml | 29 +++ examples/4g-spgw/k8s/rtr.yaml | 35 +++ examples/4g-spgw/k8s/spgw-c.yaml | 47 ++++ examples/4g-spgw/k8s/spgw-u.yaml | 71 +++++++ examples/4g-spgw/ngic-rtc/Dockerfile | 42 ++++ .../4g-spgw/ngic-rtc/config/cp/adc_rules.cfg | 44 ++++ .../4g-spgw/ngic-rtc/config/cp/interface.cfg | 5 + .../ngic-rtc/config/cp/meter_profile.cfg | 57 +++++ .../4g-spgw/ngic-rtc/config/cp/pcc_rules.cfg | 200 ++++++++++++++++++ examples/4g-spgw/ngic-rtc/config/cp/run.sh | 81 +++++++ .../4g-spgw/ngic-rtc/config/cp/sdf_rules.cfg | 38 ++++ .../4g-spgw/ngic-rtc/config/cp/simu_cp.cfg | 31 +++ .../4g-spgw/ngic-rtc/config/dp/interface.cfg | 5 + examples/4g-spgw/ngic-rtc/config/dp/run.sh | 83 ++++++++ .../4g-spgw/scripts/check-connectivity.sh | 58 +++++ examples/4g-spgw/sidecar-nse/Dockerfile | 15 ++ examples/4g-spgw/sidecar-nse/cmd/ifname.go | 89 ++++++++ examples/4g-spgw/sidecar-nse/cmd/main.go | 55 +++++ .../4g-spgw/sidecar-nse/cmd/nsc-sidecar.go | 93 ++++++++ examples/4g-spgw/sidecar-nse/cmd/runner.go | 68 ++++++ 26 files changed, 1302 insertions(+) create mode 100644 examples/4g-spgw/Makefile create mode 100644 examples/4g-spgw/README.md create mode 100644 examples/4g-spgw/dp-init/Dockerfile create mode 100755 examples/4g-spgw/dp-init/setup_af_packet.sh create mode 100644 examples/4g-spgw/enb-sim/Dockerfile create mode 100644 examples/4g-spgw/k8s/4g-network.yaml create mode 100644 examples/4g-spgw/k8s/enb-sim.yaml create mode 100644 examples/4g-spgw/k8s/rtr.yaml create mode 100644 examples/4g-spgw/k8s/spgw-c.yaml create mode 100644 examples/4g-spgw/k8s/spgw-u.yaml create mode 100644 examples/4g-spgw/ngic-rtc/Dockerfile create mode 100644 examples/4g-spgw/ngic-rtc/config/cp/adc_rules.cfg create mode 100644 examples/4g-spgw/ngic-rtc/config/cp/interface.cfg create mode 100644 examples/4g-spgw/ngic-rtc/config/cp/meter_profile.cfg create mode 100644 examples/4g-spgw/ngic-rtc/config/cp/pcc_rules.cfg create mode 100755 examples/4g-spgw/ngic-rtc/config/cp/run.sh create mode 100644 examples/4g-spgw/ngic-rtc/config/cp/sdf_rules.cfg create mode 100644 examples/4g-spgw/ngic-rtc/config/cp/simu_cp.cfg create mode 100644 examples/4g-spgw/ngic-rtc/config/dp/interface.cfg create mode 100755 examples/4g-spgw/ngic-rtc/config/dp/run.sh create mode 100755 examples/4g-spgw/scripts/check-connectivity.sh create mode 100644 examples/4g-spgw/sidecar-nse/Dockerfile create mode 100644 examples/4g-spgw/sidecar-nse/cmd/ifname.go create mode 100644 examples/4g-spgw/sidecar-nse/cmd/main.go create mode 100644 examples/4g-spgw/sidecar-nse/cmd/nsc-sidecar.go create mode 100644 examples/4g-spgw/sidecar-nse/cmd/runner.go diff --git a/examples/4g-spgw/Makefile b/examples/4g-spgw/Makefile new file mode 100644 index 0000000..848ca5d --- /dev/null +++ b/examples/4g-spgw/Makefile @@ -0,0 +1,49 @@ + +NAME = 4g-spgw +DESCRIPTION = "4G Network Topology example" +CONTAINERS = dp-init enb-sim sidecar-nse +PODS = spgw-c spgw-u enb-sim rtr +NETWORK_SERVICES = 4g-network +CHECK = scripts/check-connectivity.sh + +include $(TOP)/mk/targets.mk + + +NGIC_NAME=4g-spgw +EXTRA_CFLAGS_CP="-DUSE_AF_PACKET -DPERF_TEST -DSIMU_CP -DSTATIC_ARP -O2" +EXTRA_CFLAGS_DP="-DUSE_AF_PACKET -DPERF_TEST -DSTATIC_ARP -O2" + +.PHONY: docker-${NGIC_NAME}-ngic-build +docker-${NGIC_NAME}-ngic-build: + @docker build --target cp \ + -t ${ORG}/${NGIC_NAME}-ngic-cp \ + -f examples/${NGIC_NAME}/ngic-rtc/Dockerfile \ + --build-arg EXTRA_CFLAGS=${EXTRA_CFLAGS_CP} \ + . ; \ + docker build --target dp \ + -t ${ORG}/${NGIC_NAME}-ngic-dp \ + -f examples/${NGIC_NAME}/ngic-rtc/Dockerfile \ + --build-arg EXTRA_CFLAGS=${EXTRA_CFLAGS_DP} \ + . ; \ + if [ "x${TAG}" != "x" ] ; then \ + docker tag \ + ${ORG}/${NGIC_NAME}-ngic-cp \ + ${ORG}/${NGIC_NAME}-ngic-cp:${TAG} ; \ + docker tag \ + ${ORG}/${NGIC_NAME}-ngic-dp \ + ${ORG}/${NGIC_NAME}-ngic-dp:${TAG} ; \ + fi ; \ + +.PHONY: docker-${NGIC_NAME}-ngic-save +docker-${NGIC_NAME}-ngic-save: docker-${NGIC_NAME}-ngic-build + @for target in cp dp; do \ + echo "Saving ${ORG}/${NGIC_NAME}-ngic-$$target"; \ + mkdir -p ${NSM_PATH}/build/images/ ; \ + docker save -o ${NSM_PATH}/build/images/${NGIC_NAME}-ngic-$$target.tar ${ORG}/${NGIC_NAME}-ngic-$$target ; \ + done + +.PHONY: $(PREFIX)-$(NGIC_NAME)-ngic-load-images +$(PREFIX)-$(NGIC_NAME)-ngic-load-images: + @for target in cp dp; do \ + make $(CLUSTER_RULES_PREFIX)-$(NGIC_NAME)-ngic-$$target-load-images ; \ + done diff --git a/examples/4g-spgw/README.md b/examples/4g-spgw/README.md new file mode 100644 index 0000000..bdd08e6 --- /dev/null +++ b/examples/4g-spgw/README.md @@ -0,0 +1,37 @@ +# 4G EPC SPGW example + +An example the leverages the OMEC's NGIC-RTC implementation of S-GW/P-GW. + +``` + +----------------+ + | | + | SPGW+C | + | | + | | + | | + | | + Control plane +--------+-------+ + | + | Sx ++------------------------------------------------------------------------------------+ + | + | + +----------------+ Data plane +--------v-------+ +----------------+ + | | | | | | + | | | SPGW+U | | RTR | + | eNB-sim | S1U | | SGi | | + | +------------------> 10.60.3.0/24 +----------> 10.60.2.0/24 | + | | | | | | + | | | | | | + +----------------+ +----------------+ +----------------+ + +``` + +The NGIC is compiled with a SIMU_CP flag so no MME is needed. + +References: + * https://www.youtube.com/watch?v=fry7zmNmJ10 + * https://www.opennetworking.org/wp-content/uploads/2019/09/2pm-Saikrishna-Edupuganti-OMEC-in-a-Kubernetes-Orchestrated-Environment.pdf + * https://github.com/omec-project/ngic-rtc/tree/master/deploy/k8s + * https://github.com/opencord/helm-charts/tree/master/omec + * https://www.slideshare.net/kentaroebisawa/using-gtp-on-linux-with-libgtpnl diff --git a/examples/4g-spgw/dp-init/Dockerfile b/examples/4g-spgw/dp-init/Dockerfile new file mode 100644 index 0000000..f41bd39 --- /dev/null +++ b/examples/4g-spgw/dp-init/Dockerfile @@ -0,0 +1,4 @@ +FROM ubuntu:20.04 +COPY ./examples/4g-spgw/dp-init/setup_af_packet.sh /opt/dp/setup_af_packet.sh +RUN apt update && apt -y dist-upgrade && apt install -y iproute2 && rm -rf /var/lib/apt/lists/* +ENTRYPOINT ["/opt/dp/setup_af_packet.sh"] diff --git a/examples/4g-spgw/dp-init/setup_af_packet.sh b/examples/4g-spgw/dp-init/setup_af_packet.sh new file mode 100755 index 0000000..1157e0f --- /dev/null +++ b/examples/4g-spgw/dp-init/setup_af_packet.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -x +set -o errexit +set -o pipefail +set -o nounset + +##S1U INTERFACE## +UL_IFACE="S1Udev" +##SGI INTERFACE## +DL_IFACE="SGIdev" + +ip a + +ip link add $UL_IFACE type veth peer name l_$UL_IFACE +ip link add $DL_IFACE type veth peer name l_$DL_IFACE +ip link set $UL_IFACE up +ip link set $DL_IFACE up +ip link set l_$UL_IFACE up +ip link set l_$DL_IFACE up diff --git a/examples/4g-spgw/enb-sim/Dockerfile b/examples/4g-spgw/enb-sim/Dockerfile new file mode 100644 index 0000000..ba6e253 --- /dev/null +++ b/examples/4g-spgw/enb-sim/Dockerfile @@ -0,0 +1,17 @@ +FROM ubuntu:20.04 as build +RUN apt update && apt -y dist-upgrade +RUN apt install -y build-essential git autoconf libmnl-dev libtool pkg-config +RUN git clone git://git.osmocom.org/libgtpnl +RUN cd libgtpnl/ && autoreconf -fi && ./configure --enable-static --disable-shared && make +RUN pwd && ls -laR /libgtpnl +RUN ldd /libgtpnl/tools/gtp-link + +FROM ubuntu:20.04 as runtime +RUN apt update && \ + apt -y dist-upgrade && \ + apt install -y \ + libmnl0 iproute2 netcat-openbsd iputils-ping curl && \ + apt clean && \ + rm -rf /var/lib/apt/lists/* +COPY --from=build /libgtpnl/tools/gtp-link /opt/gtp-link +COPY --from=build /libgtpnl/tools/gtp-tunnel /opt/gtp-tunnel \ No newline at end of file diff --git a/examples/4g-spgw/k8s/4g-network.yaml b/examples/4g-spgw/k8s/4g-network.yaml new file mode 100644 index 0000000..f87b32a --- /dev/null +++ b/examples/4g-spgw/k8s/4g-network.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: networkservicemesh.io/v1alpha1 +kind: NetworkService +metadata: + name: 4g-network +spec: + payload: IP + matches: + - match: + sourceSelector: + name: sx + route: + - destination: + destinationSelector: + app: spgw-u + - match: + sourceSelector: + name: s1u + route: + - destination: + destinationSelector: + app: spgw-u + - match: + sourceSelector: + name: sgi + route: + - destination: + destinationSelector: + app: rtr diff --git a/examples/4g-spgw/k8s/enb-sim.yaml b/examples/4g-spgw/k8s/enb-sim.yaml new file mode 100644 index 0000000..d152dfb --- /dev/null +++ b/examples/4g-spgw/k8s/enb-sim.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: apps/v1 +kind: Deployment +spec: + replicas: 1 + selector: + matchLabels: + networkservicemesh.io/app: "enb-sim" + template: + metadata: + labels: + networkservicemesh.io/app: "enb-sim" + networkservicemesh.io/impl: "4g-network" + spec: + containers: + - name: enb-sim + image: networkservicemesh/4g-spgw-enb-sim:latest + command: ['tail', '-f', '/dev/null'] + imagePullPolicy: IfNotPresent + securityContext: + capabilities: + add: + - NET_ADMIN + privileged: true +metadata: + name: enb-sim + namespace: default + annotations: + ns.networkservicemesh.io: 4g-network/s1u?name=s1u diff --git a/examples/4g-spgw/k8s/rtr.yaml b/examples/4g-spgw/k8s/rtr.yaml new file mode 100644 index 0000000..d32f320 --- /dev/null +++ b/examples/4g-spgw/k8s/rtr.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: apps/v1 +kind: Deployment +spec: + selector: + matchLabels: + networkservicemesh.io/app: "rtr" + replicas: 1 + template: + metadata: + labels: + networkservicemesh.io/app: "rtr" + spec: + containers: + - name: sidecar-nse + image: networkservicemesh/4g-spgw-sidecar-nse:latest + imagePullPolicy: IfNotPresent + env: + - name: ENDPOINT_NETWORK_SERVICE + value: "4g-network" + - name: ENDPOINT_LABELS + value: "app=rtr" + - name: TRACER_ENABLED + value: "true" + - name: IP_ADDRESS + value: "10.60.2.0/24" + resources: + limits: + networkservicemesh.io/socket: 1 + - name: rtr + image: alpine:latest + command: ['tail', '-f', '/dev/null'] +metadata: + name: "rtr" + namespace: default diff --git a/examples/4g-spgw/k8s/spgw-c.yaml b/examples/4g-spgw/k8s/spgw-c.yaml new file mode 100644 index 0000000..7199ca6 --- /dev/null +++ b/examples/4g-spgw/k8s/spgw-c.yaml @@ -0,0 +1,47 @@ +--- +apiVersion: apps/v1 +kind: Deployment +spec: + replicas: 1 + selector: + matchLabels: + networkservicemesh.io/app: "spgw-c" + template: + metadata: + labels: + networkservicemesh.io/app: "spgw-c" + spec: + containers: + - name: cp + image: "networkservicemesh/4g-spgw-ngic-cp:latest" + imagePullPolicy: IfNotPresent + stdin: true + tty: true + command: ["/opt/cp/config/run.sh"] + env: + - name: MEM_LIMIT + valueFrom: + resourceFieldRef: + containerName: cp + resource: limits.memory + divisor: 1Mi + volumeMounts: + #- name: hugepage + # mountPath: /dev/hugepages + resources: + limits: + #hugepages-2Mi: 2Gi + cpu: 2 + memory: 200Mi #3Gi + volumes: + - name: shared-data + emptyDir: {} + #- name: hugepage + # emptyDir: + # medium: HugePages +metadata: + name: "spgw-c" + namespace: default + annotations: + ns.networkservicemesh.io: 4g-network/sx?name=sx + diff --git a/examples/4g-spgw/k8s/spgw-u.yaml b/examples/4g-spgw/k8s/spgw-u.yaml new file mode 100644 index 0000000..60ecaac --- /dev/null +++ b/examples/4g-spgw/k8s/spgw-u.yaml @@ -0,0 +1,71 @@ +--- +apiVersion: apps/v1 +kind: Deployment +spec: + replicas: 1 + selector: + matchLabels: + networkservicemesh.io/app: "spgw-u" + template: + metadata: + labels: + networkservicemesh.io/app: "spgw-u" + networkservicemesh.io/impl: "4g-network" + spec: + initContainers: + - name: dp-init-container + image: networkservicemesh/4g-spgw-dp-init:latest + imagePullPolicy: IfNotPresent + securityContext: + capabilities: + add: + - NET_ADMIN + containers: + - name: sidecar-nse + image: networkservicemesh/4g-spgw-sidecar-nse:latest + imagePullPolicy: IfNotPresent + env: + - name: NS_NETWORKSERVICEMESH_IO + value: "4g-network/sgi?name=sgi" + - name: ENDPOINT_NETWORK_SERVICE + value: "4g-network" + - name: ENDPOINT_LABELS + value: "app=spgw-u" + - name: TRACER_ENABLED + value: "true" + - name: IP_ADDRESS + value: "10.60.3.0/24" + resources: + limits: + networkservicemesh.io/socket: "1" + - name: dp + image: "networkservicemesh/4g-spgw-ngic-dp:latest" + imagePullPolicy: IfNotPresent + securityContext: + capabilities: + add: + - NET_ADMIN + privileged: true + env: + command: ['tail', '-f', '/dev/null'] + volumeMounts: + #- name: hugepage + # mountPath: /dev/hugepages + resources: + limits: + #hugepages-2Mi: 4Gi + cpu: 2 + memory: 200Mi #5Gi + # securityContext: + # capabilities: + # add: + # - IPC_LOCK + volumes: + #- name: hugepage + # emptyDir: + # medium: HugePages +metadata: + name: spgw-u + namespace: default + annotations: + ns.networkservicemesh.io: 4g-network/sgi?name=sgi diff --git a/examples/4g-spgw/ngic-rtc/Dockerfile b/examples/4g-spgw/ngic-rtc/Dockerfile new file mode 100644 index 0000000..2f4dbda --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/Dockerfile @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2019-present Open Networking Foundation +# Copyright (c) 2019 Intel Corporation +# Copyright 2020 VMware, Inc. + +# Multi-stage Dockerfile +ARG BASE_OS=ubuntu:18.04 + +## Stage build: kitchen sink stage for compiling dependencies and CP/DP bins +FROM $BASE_OS as build +ARG CPUS=2 +ARG RTE_MACHINE=hsw +ARG EXTRA_CFLAGS='-DUSE_AF_PACKET -O2' + +WORKDIR / +SHELL ["/bin/bash", "-c"] + +RUN apt-get update && apt-get install -y git +RUN git clone --depth 1 --single-branch https://github.com/omec-project/ngic-rtc.git +WORKDIR /ngic-rtc +RUN ./install_builddeps.sh +RUN source ./install_builddeps.sh && make -j $CPUS clean && make -j $CPUS RTE_MACHINE=$RTE_MACHINE EXTRA_CFLAGS="$EXTRA_CFLAGS" + +## Stage runtime: no utils +FROM $BASE_OS as runtime +SHELL ["/bin/bash", "-c"] +COPY --from=build /ngic-rtc/install_rundeps.sh . +RUN source ./install_rundeps.sh && install_run_utils && apt install -y vim && cleanup_image + +## Stage cp: creates the runtime image of control plane +FROM runtime as cp +RUN source ./install_rundeps.sh && install_run_cp_deps && cleanup_image +COPY --from=build /ngic-rtc/cp/build/ngic_controlplane /bin/ngic_controlplane +COPY ./examples/4g-spgw/ngic-rtc/config/cp /opt/cp/config + + +## Stage dp: creates the runtime image of data plane +FROM runtime as dp +RUN source ./install_rundeps.sh && install_run_dp_deps && cleanup_image +COPY --from=build /ngic-rtc/dp/build/ngic_dataplane /bin/ngic_dataplane +COPY ./examples/4g-spgw/ngic-rtc/config/dp /opt/dp/config + diff --git a/examples/4g-spgw/ngic-rtc/config/cp/adc_rules.cfg b/examples/4g-spgw/ngic-rtc/config/cp/adc_rules.cfg new file mode 100644 index 0000000..e85afdc --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/config/cp/adc_rules.cfg @@ -0,0 +1,44 @@ +[GLOBAL] +NUM_ADC_RULES = 5 + +;FORMAT :: +;ADC_TYPE : [ DOMAIN = 0 | IP = 1 | IP PREFIX =2 ] +; +;if ADC_TYPE = 0 +; DOMAIN +;elseif ADC_TYPE = 1 +; IP +;elseif ADC_TYPE = 2 +; IP +; PREFIX +;else +; NONE +; +;NOTE : +;Rules defined first have a higher priority, unless DROP is specified +;(i.e. multiple rules for the same IP). +;When specifying DROP with an IP address, use a prefix of 32 to prevent DNS +;results from overwriting rule. + + +[ADC_RULE_1] +ADC_TYPE = 1 +IP = 13.1.1.111 + +[ADC_RULE_2] +ADC_TYPE = 2 +IP = 13.1.1.0 +PREFIX = 24 + +[ADC_RULE_3] +ADC_TYPE = 1 +IP = 13.1.1.112 +PREFIX = 24 + +[ADC_RULE_4] +ADC_TYPE = 0 +DOMAIN = www.example.gov + +[ADC_RULE_5] +ADC_TYPE = 0 +DOMAIN = www.drop_example.com diff --git a/examples/4g-spgw/ngic-rtc/config/cp/interface.cfg b/examples/4g-spgw/ngic-rtc/config/cp/interface.cfg new file mode 100644 index 0000000..d9a8ea1 --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/config/cp/interface.cfg @@ -0,0 +1,5 @@ +[0] +dp_comm_ip = DP_COMM_IP +dp_comm_port = 20 +cp_comm_ip = CP_COMM_IP +cp_comm_port = 21 diff --git a/examples/4g-spgw/ngic-rtc/config/cp/meter_profile.cfg b/examples/4g-spgw/ngic-rtc/config/cp/meter_profile.cfg new file mode 100644 index 0000000..10ccfb9 --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/config/cp/meter_profile.cfg @@ -0,0 +1,57 @@ +[GLOBAL] +NUM_OF_IDX = 7 + +[ENTRY_1] +;Committed Information Rate (CIR). Measured in bytes per second. +;MBR is mapped into CIR, convert MBR from bits to Bytes and set CIR. +CIR = 2342400 +;Committed Burst Size unit = Bytes +CBS = 5856 +;Excess Burst Size unit = Bytes +EBS = 11712 +;Meter profile index. Refer this index in static_pcc.cfg to set AMBR/MBR +MTR_PROFILE_IDX = 3 + +[ENTRY_2] +;1200 = 1756800 +;1400 = 2049600 +;1600 = 2342400 +CIR = 2342400 +CBS = 5856 +EBS = 11712 +MTR_PROFILE_IDX = 4 + +[ENTRY_3] +; QCI5,QCI7 15.571kbps = 1947 B +CIR = 2342400 +CBS = 5856 +EBS = 11712 +MTR_PROFILE_IDX = 5 + +[ENTRY_4] +; QCI1, 44kbps = 5500 B +CIR = 2342400 +CBS = 5856 +EBS = 11712 +MTR_PROFILE_IDX = 6 + +[ENTRY_5] +; QCI9, 31.143kbps = 3893 B +CIR = 2342400 +CBS = 5856 +EBS = 11712 +MTR_PROFILE_IDX = 7 + +[ENTRY_6] +; 128B, 7pps +CIR = 2342400 +CBS = 512 +EBS = 1024 +MTR_PROFILE_IDX = 8 + +[ENTRY_7] +; 128B, 2pps +CIR = 2342400 +CBS = 512 +EBS = 1024 +MTR_PROFILE_IDX = 9 diff --git a/examples/4g-spgw/ngic-rtc/config/cp/pcc_rules.cfg b/examples/4g-spgw/ngic-rtc/config/cp/pcc_rules.cfg new file mode 100644 index 0000000..8b3ffbc --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/config/cp/pcc_rules.cfg @@ -0,0 +1,200 @@ +[GLOBAL] +NUM_PCC_FILTERS = 9 +;To config AMBR/MBR values refer meter_profile.cfg. specify only the +;meter profile index to be set here. +UL_AMBR_MTR_PROFILE_IDX = 3 +DL_AMBR_MTR_PROFILE_IDX = 4 + +;default filter - must be first for now (until DP doesn't install any filters) +;associated with default adc rule +[PCC_FILTER_1] +RULE_NAME = DefaultRule +RATING_GROUP = 9 +SERVICE_ID = 0 +RULE_STATUS = 0 +GATE_STATUS = 1 +SESSION_CONT = 0 +REPORT_LEVEL = 1 +CHARGING_MODE = 0 +METERING_METHOD = 0 +MUTE_NOTIFY = 0 +MONITORING_KEY = 0 +SPONSOR_ID = 0 +REDIRECT_INFO = 0 +PRECEDENCE = 254 +DROP_PKT_COUNT = 0 +;Specify the meter profile index from meter_profile.cfg +UL_MBR_MTR_PROFILE_IDX = 7 +DL_MBR_MTR_PROFILE_IDX = 7 +;List of ADC filter indices +SDF_FILTER_IDX = 99998 + +[PCC_FILTER_2] +RULE_NAME = sdf_rule_1 +RATING_GROUP = 5 +SERVICE_ID = 0 +RULE_STATUS = 0 +GATE_STATUS = 1 +SESSION_CONT = 0 +REPORT_LEVEL = 2 +CHARGING_MODE = 0 +METERING_METHOD = 0 +MUTE_NOTIFY = 0 +MONITORING_KEY = 0 +SPONSOR_ID = 0 +REDIRECT_INFO = 0 +PRECEDENCE = 1 +DROP_PKT_COUNT = 0 +UL_MBR_MTR_PROFILE_IDX = 5 +DL_MBR_MTR_PROFILE_IDX = 5 +;List of SDF filter indices +SDF_FILTER_IDX = 1 + +[PCC_FILTER_3] +RULE_NAME = sdf_rule_2 +RATING_GROUP = 1 +SERVICE_ID = 0 +RULE_STATUS = 0 +GATE_STATUS = 1 +SESSION_CONT = 0 +REPORT_LEVEL = 3 +CHARGING_MODE = 0 +METERING_METHOD = 0 +MUTE_NOTIFY = 0 +MONITORING_KEY = 0 +SPONSOR_ID = 0 +REDIRECT_INFO = 0 +PRECEDENCE = 18 +DROP_PKT_COUNT = 0 +UL_MBR_MTR_PROFILE_IDX = 6 +DL_MBR_MTR_PROFILE_IDX = 6 +;List of SDF filter indices +SDF_FILTER_IDX = 2 + +[PCC_FILTER_4] +RULE_NAME = adc_rule_1 +RATING_GROUP = Zero-Rate +SERVICE_ID = Internet +RULE_STATUS = 0 +GATE_STATUS = 1 +SESSION_CONT = 0 +REPORT_LEVEL = 8 +CHARGING_MODE = 0 +METERING_METHOD = 0 +MUTE_NOTIFY = 0 +MONITORING_KEY = 0 +REDIRECT_INFO = 0 +SPONSOR_ID = Example +PRECEDENCE = 15 +DROP_PKT_COUNT = 0 +UL_MBR_MTR_PROFILE_IDX = 7 +DL_MBR_MTR_PROFILE_IDX = 7 +;List of SDF filter indices +ADC_FILTER_IDX = 1 + +[PCC_FILTER_5] +RULE_NAME = adc_rule_2 +RATING_GROUP = 0 +SERVICE_ID = CIPA +RULE_STATUS = 0 +GATE_STATUS = 1 +SESSION_CONT = 0 +REPORT_LEVEL = 9 +CHARGING_MODE = 0 +METERING_METHOD = 0 +MUTE_NOTIFY = 0 +MONITORING_KEY = 0 +SPONSOR_ID = Example +REDIRECT_INFO = 0 +SPONSOR_ID = Example +REDIRECT_INFO = 0 +PRECEDENCE = 4 +DROP_PKT_COUNT = 0 +UL_MBR_MTR_PROFILE_IDX = 0 +DL_MBR_MTR_PROFILE_IDX = 0 +;List of SDF filter indices +ADC_FILTER_IDX = 2 + +[PCC_FILTER_6] +RULE_NAME = sdf_rule_3 +RATING_GROUP = 7 +SERVICE_ID = 0 +RULE_STATUS = 0 +GATE_STATUS = 1 +SESSION_CONT = 0 +REPORT_LEVEL = 4 +CHARGING_MODE = 0 +METERING_METHOD = 0 +MUTE_NOTIFY = 0 +MONITORING_KEY = 0 +SPONSOR_ID = 0 +REDIRECT_INFO = 0 +PRECEDENCE = 17 +DROP_PKT_COUNT = 0 +UL_MBR_MTR_PROFILE_IDX = 5 +DL_MBR_MTR_PROFILE_IDX = 5 +;List of SDF filter indices +SDF_FILTER_IDX = 3 + +[PCC_FILTER_7] +RULE_NAME = adc_rule_3 +RATING_GROUP = Zero-Rate +SERVICE_ID = Internet +RULE_STATUS = 0 +GATE_STATUS = 1 +SESSION_CONT = 0 +REPORT_LEVEL = 5 +CHARGING_MODE = 0 +METERING_METHOD = 0 +MUTE_NOTIFY = 0 +MONITORING_KEY = 0 +SPONSOR_ID = Example +REDIRECT_INFO = 0 +PRECEDENCE = 210 +DROP_PKT_COUNT = 0 +UL_MBR_MTR_PROFILE_IDX = 7 +DL_MBR_MTR_PROFILE_IDX = 7 +;List of SDF filter indices +ADC_FILTER_IDX = 4 + +[PCC_FILTER_8] +RULE_NAME = adc_rule_4 +RATING_GROUP = Zero-Rate +SERVICE_ID = Management +RULE_STATUS = 0 +GATE_STATUS = 1 +SESSION_CONT = 0 +REPORT_LEVEL = 6 +CHARGING_MODE = 0 +METERING_METHOD = 0 +MUTE_NOTIFY = 0 +MONITORING_KEY = 0 +SPONSOR_ID = Example +REDIRECT_INFO = 0 +PRECEDENCE = 200 +DROP_PKT_COUNT = 0 +UL_MBR_MTR_PROFILE_IDX = 7 +DL_MBR_MTR_PROFILE_IDX = 7 +;List of SDF filter indices +ADC_FILTER_IDX = 12 + +[PCC_FILTER_9] +RULE_NAME = adc_rule_5 +RATING_GROUP = Zero-Rate +SERVICE_ID = Provisioning +RULE_STATUS = 0 +GATE_STATUS = 1 +SESSION_CONT = 0 +REPORT_LEVEL = 7 +CHARGING_MODE = 0 +METERING_METHOD = 0 +MUTE_NOTIFY = 0 +MONITORING_KEY = 0 +SPONSOR_ID = Example +REDIRECT_INFO = 0 +PRECEDENCE = 220 +DROP_PKT_COUNT = 0 +UL_MBR_MTR_PROFILE_IDX = 7 +DL_MBR_MTR_PROFILE_IDX = 7 +;List of SDF filter indices +ADC_FILTER_IDX = 3 diff --git a/examples/4g-spgw/ngic-rtc/config/cp/run.sh b/examples/4g-spgw/ngic-rtc/config/cp/run.sh new file mode 100755 index 0000000..fba6770 --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/config/cp/run.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +RUN_DIR="/opt/cp/config" +CNI_IF="eth0" +SX_IF="sx" + +cd ${RUN_DIR} + +nextip(){ + IP=$1 + IP_HEX=$(printf '%.2X%.2X%.2X%.2X\n' `echo $IP | sed -e 's/\./ /g'`) + NEXT_IP_HEX=$(printf %.8X `echo $(( 0x$IP_HEX + 1 ))`) + NEXT_IP=$(printf '%d.%d.%d.%d\n' `echo $NEXT_IP_HEX | sed -r 's/(..)/0x\1 /g'`) + echo "$NEXT_IP" +} + +CNI_IP=$(ip -4 addr show dev ${CNI_IF} | grep -oP '(?<=inet\s)\d+(\.\d+){3}') +CP_COMM_IP=$(ip -4 addr show dev ${SX_IF} | grep -oP '(?<=inet\s)\d+(\.\d+){3}') +DP_COMM_IP=$(nextip $CP_COMM_IP) + +sed -i "s/CP_COMM_IP/$CP_COMM_IP/g" interface.cfg +sed -i "s/DP_COMM_IP/$DP_COMM_IP/g" interface.cfg + + +# {"spgw_cfg", required_argument, NULL, 'd'}, +# {"s11_mme_ip", required_argument, NULL, 'm'}, +# {"s11_sgw_ip", required_argument, NULL, 's'}, +# {"s5s8_sgwc_ip", optional_argument, NULL, 'r'}, +# {"s5s8_pgwc_ip", optional_argument, NULL, 'g'}, +# {"s1u_sgw_ip", required_argument, NULL, 'w'}, +# {"s5s8_sgwu_ip", optional_argument, NULL, 'v'}, +# {"s5s8_pgwu_ip", optional_argument, NULL, 'u'}, +# {"ip_pool_ip", required_argument, NULL, 'i'}, +# {"ip_pool_mask", required_argument, NULL, 'p'}, +# {"apn_name", required_argument, NULL, 'a'}, +# {"log_level", required_argument, NULL, 'l'}, +# {"pcap_file_in", required_argument, NULL, 'x'}, +# {"pcap_file_out", required_argument, NULL, 'y'}, + +# | ARGUMENT | PRESENCE | DESCRIPTION | +# |:-------------------|:------------|:-------------------------------------------| +# | --SPGW_CFG | MANDATORY | CP run setup:01(SGWC), 02(PGWC),03(SPGWC) | +# | --s11_sgw_ip | MANDATORY | Local interface IP exposed to Linux | +# | | | networking stack to be used by the Control | +# | | | Plane for messaging with the MME | +# | --s11_mme_ip | MANDATORY | MME IP | +# | --s1u_sgw_ip | MANDATORY | Network interface IP exposed by DP; must be| +# | | | equivalent to --s1u_ip parameter of DP | +# | --s5s8_sgwc_ip | OPTIONAL | Applicable in case of SGWC configuration | +# | --s5s8_sgwu_ip | OPTIONAL | Applicable in case of SGWC configuration | +# | --s5s8_pgwc_ip | OPTIONAL | Applicable in case of PGWC configuration | +# | --s5s8_pgwu_ip | OPTIONAL | Applicable in case of PGWC configuration | +# | --ip_pool_ip | MANDATORY | Along with mask, defines pool of IP | +# | | | addresses that CP may assign to UEs | +# | --ip_pool_mask | MANDATORY | ip_pool_mask | +# | --apn_name | MANDATORY | Access Point Name label supported by CP; | +# | | | must correspond to APN referenced in create| +# | | | session request messages along the s11 | +# | --pcap_file_in | OPTIONAL | Ignores s11 interface and acts as if | +# | | | packets contained in input file arrived | +# | | | from MME | +# | --pcap_file_out | OPTIONAL | Creates a capture of messages created by | +# | | | CP. Mainly for development purposes | +# | --memory | MANDATORY | Memory size for hugepages setup | +# | --numa0_memory | MANDATORY | Socket memory related to numa0 socket | +# | --numa1_memory | MANDATORY | Socket memory related to numa1 socket | +# |:-------------------|:------------|:-------------------------------------------| + +/bin/ngic_controlplane \ + -c 3f --no-huge -m 2048 --no-pci -- \ + --s11_sgw_ip ${CNI_IP} \ + --s1u_sgw_ip 11.1.1.1 \ + --ip_pool_ip 16.0.0.0 \ + --ip_pool_mask 255.0.0.0 \ + --apn_name apn1 \ + --spgw_cfg 03 \ + --log_level 2 \ + # --s5s8_sgwc_ip 7.7.7.7 \ + # --s5s8_pgwc_ip 6.6.6.6 \ + # --s5s8_sgwu_ip 4.4.4.4 \ + # --s5s8_pgwu_ip 5.5.5.5 diff --git a/examples/4g-spgw/ngic-rtc/config/cp/sdf_rules.cfg b/examples/4g-spgw/ngic-rtc/config/cp/sdf_rules.cfg new file mode 100644 index 0000000..2b6c244 --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/config/cp/sdf_rules.cfg @@ -0,0 +1,38 @@ +[GLOBAL] +NUM_SDF_FILTERS = 4 + +[SDF_FILTER_1] +DIRECTION = downlink_only +IPV4_REMOTE = 13.2.1.113 +IPV4_REMOTE_MASK = 255.255.255.0 +PROTOCOL = 17 +LOCAL_LOW_LIMIT_PORT = 0 +LOCAL_HIGH_LIMIT_PORT = 65535 +REMOTE_LOW_LIMIT_PORT = 0 +REMOTE_HIGH_LIMIT_PORT = 65535 + +[SDF_FILTER_2] +DIRECTION = uplink_only +IPV4_LOCAL = 16.255.255.0 +IPV4_LOCAL_MASK = 255.255.255.0 +PROTOCOL = 17 +LOCAL_LOW_LIMIT_PORT = 0 +LOCAL_HIGH_LIMIT_PORT = 65535 +REMOTE_LOW_LIMIT_PORT = 0 +REMOTE_HIGH_LIMIT_PORT = 65535 + +[SDF_FILTER_3] +DIRECTION = downlink_only +IPV4_REMOTE = 130.10.0.0 +IPV4_REMOTE_MASK = 255.255.0.0 +PROTOCOL = 17 +REMOTE_LOW_LIMIT_PORT = 5060 +REMOTE_HIGH_LIMIT_PORT = 5060 + +[SDF_FILTER_4] +DIRECTION = uplink_only +IPV4_REMOTE = 103.1.0.0 +IPV4_REMOTE_MASK = 255.255.0.0 +PROTOCOL = 17 +LOCAL_LOW_LIMIT_PORT = 17000 +LOCAL_HIGH_LIMIT_PORT = 17010 diff --git a/examples/4g-spgw/ngic-rtc/config/cp/simu_cp.cfg b/examples/4g-spgw/ngic-rtc/config/cp/simu_cp.cfg new file mode 100644 index 0000000..12c91ec --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/config/cp/simu_cp.cfg @@ -0,0 +1,31 @@ +; SPDX-License-Identifier: Apache-2.0 +; Copyright(c) 2017 Intel Corporation + +[0] +S1U_SGW_IP=11.7.1.93 +ENODEB_IP_START = 11.7.1.101 +UE_IP_START = 16.0.0.1 +UE_IP_START_RANGE = 16.0.0.0 +AS_IP_START = 13.7.1.110 +MAX_UE_SESS = 10000 +TPS = 10000 +BREAK_DURATION = 60 +DEFAULT_BEARER = 5 +ng4t_max_ue_ran = 500000 +ng4t_max_enb_ran = 80 + + + +enodeb_ip = 11.1.1.101 +ue_ip_start = 16.0.0.1 +ue_ip_start_range = 16.0.0.0 +as_ip_start = 13.1.1.110 +max_entries = 100 +max_rules = 24 +max_ul_rules = 12 +max_dl_rules = 12 +max_ue_sess = 1000 +max_meter_profile_entries = 100 +default_bearer = 5 +dedicated_bearer = 0 + diff --git a/examples/4g-spgw/ngic-rtc/config/dp/interface.cfg b/examples/4g-spgw/ngic-rtc/config/dp/interface.cfg new file mode 100644 index 0000000..d9a8ea1 --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/config/dp/interface.cfg @@ -0,0 +1,5 @@ +[0] +dp_comm_ip = DP_COMM_IP +dp_comm_port = 20 +cp_comm_ip = CP_COMM_IP +cp_comm_port = 21 diff --git a/examples/4g-spgw/ngic-rtc/config/dp/run.sh b/examples/4g-spgw/ngic-rtc/config/dp/run.sh new file mode 100755 index 0000000..95e9bae --- /dev/null +++ b/examples/4g-spgw/ngic-rtc/config/dp/run.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash + +RUN_DIR="/opt/dp/config" +CNI_IF="eth0" +SX_IF="sx" +##S1U INTERFACE## +S1U_IF="s1u" +UL_IFACE="S1Udev" +##SGI INTERFACE## +SGI_IF="sgi" +DL_IFACE="SGIdev" +RTR_SGI_IP="13.1.1.110" +RTR_SGI_MASK="255.255.255.192" + + +cd ${RUN_DIR} + +previp(){ + IP=$1 + IP_HEX=$(printf '%.2X%.2X%.2X%.2X\n' `echo $IP | sed -e 's/\./ /g'`) + NEXT_IP_HEX=$(printf %.8X `echo $(( 0x$IP_HEX -1 ))`) + NEXT_IP=$(printf '%d.%d.%d.%d\n' `echo $NEXT_IP_HEX | sed -r 's/(..)/0x\1 /g'`) + echo "$NEXT_IP" +} + +CNI_IP=$(ip -4 addr show dev ${CNI_IF} | grep -oP '(?<=inet\s)\d+(\.\d+){3}') +CP_COMM_IP=$(ip -4 addr show dev ${SX_IF} | grep -oP '(?<=inet\s)\d+(\.\d+){3}') +DP_COMM_IP=$(previp $CP_COMM_IP) + +sed -i "s/CP_COMM_IP/$CP_COMM_IP/g" interface.cfg +sed -i "s/DP_COMM_IP/$DP_COMM_IP/g" interface.cfg + +S1U_IP=$(ip -4 addr show dev ${S1U_IF} | grep -oP '(?<=inet\s)\d+(\.\d+){3}') +SGI_IP=$(ip -4 addr show dev ${SGI_IF} | grep -oP '(?<=inet\s)\d+(\.\d+){3}') +S1U_MAC=$(ip addr show dev ${S1U_IF} | awk '$1=="link/ether"{print $2}') +SGI_MAC=$(ip addr show dev ${SGI_IF} | awk '$1=="link/ether"{print $2}') +S1U="--s1u_ip ${S1U_IP} --s1u_mac ${S1U_MAC} --ul_iface ${UL_IFACE}" +SGI="--sgi_ip ${SGI_IP} --sgi_mac ${SGI_MAC} --dl_iface ${DL_IFACE} --sgi_gw_ip ${RTR_SGI_IP} --sgi_mask ${RTR_SGI_MASK}" + + +# ======================================================================= +# Setup AF_PACKET + +calc_cidrmask() { + local CIDR_MASK=0 + local DOTTED_MASK=$1 + for octet in $(echo $DOTTED_MASK | sed 's/\./ /g'); do + binbits=$(echo "obase=2; ibase=10; ${octet}"| bc | sed 's/0//g') + let CIDR_MASK+=${#binbits} + done + + echo $CIDR_MASK +} + +# SUDO='' +# [[ $EUID -ne 0 ]] && SUDO=sudo + +# $SUDO ip link add $UL_IFACE type veth peer name l_$UL_IFACE +# $SUDO ip link add $DL_IFACE type veth peer name l_$DL_IFACE +# $SUDO ip link set $UL_IFACE up +# $SUDO ip link set $DL_IFACE up +# $SUDO ip link set l_$UL_IFACE up +# $SUDO ip link set l_$DL_IFACE up +$SUDO ip link set dev $UL_IFACE address $S1U_MAC +$SUDO ip link set dev $DL_IFACE address $SGI_MAC + +CIDR_MASK=$(calc_cidrmask $S1U_MASK) +$SUDO ip addr add $S1U_IP/$CIDR_MASK dev $UL_IFACE + +CIDR_MASK=$(calc_cidrmask $SGI_MASK) +$SUDO ip addr add $SGI_IP/$CIDR_MASK dev $DL_IFACE + +ip route + +# ======================================================================= + +/bin/ngic_dataplane \ + -c 3f --no-huge -m 2048 --no-pci \ + --vdev eth_af_packet1,iface=${S1U_IF} --vdev eth_af_packet2,iface=${SGI_IF} -- \ + ${S1U} \ + ${SGI} \ + --log 1 \ + --spgw_cfg 03 diff --git a/examples/4g-spgw/scripts/check-connectivity.sh b/examples/4g-spgw/scripts/check-connectivity.sh new file mode 100755 index 0000000..77543fa --- /dev/null +++ b/examples/4g-spgw/scripts/check-connectivity.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +kubectl wait -n default --timeout=150s --for condition=Ready --all pods + +CLIENTS="p-gw-u s-gw-c" +ENDPOINTS="p-gw-c s-gw-u" + +# Ping all the things! +EXIT_VAL=0 +for client in ${CLIENTS}; do + for nsc in $(kubectl get pods -o=name | grep -E "${client}" | sed 's@.*/@@'); do + echo "===== >>>>> PROCESSING ${nsc} <<<<< ===========" + for ip in $(kubectl exec -it -c "${client}" "${nsc}" -- ip addr| grep inet | awk '{print $2}'); do + if [[ "${ip}" == 10.60.*.* ]];then + firstSegment=$(echo "${ip}" | cut -d . -f 1-3) + lastSegment=$(echo "${ip}" | cut -d . -f 4 | cut -d / -f 1) + nextOp=$((lastSegment + 1)) + targetIp="${firstSegment}.${nextOp}" + # Get the name of its corresponding endpoint pair + for endpoint in ${ENDPOINTS}; do + for nse in $(kubectl get pods -o=name | grep -E "${endpoint}" | sed 's@.*/@@'); do + for ip_e in $(kubectl exec -it -c "${endpoint}" "${nse}" -- ip addr| grep inet | awk '{print $2}'); do + if [[ "${ip_e}" == "${targetIp}/30" ]];then + echo "===== >>>>> ENDPOINT PAIR - ${nse} <<<<< ===========" + endpointName="${nse}" + fi + done + done + done + fi + # Do the actual pinging once we have the target IP address + if [ -n "${targetIp}" ]; then + if kubectl exec -it -c "${client}" "${nsc}" -- ping -c 1 "${targetIp}" ; then + echo "NSC ${nsc} with IP ${ip} pinging ${endpointName} TargetIP: ${targetIp} successful" + PingSuccess="true" + else + echo "NSC ${nsc} with IP ${ip} pinging ${endpointName} TargetIP: ${targetIp} unsuccessful" + EXIT_VAL=1 + fi + unset targetIp + unset endpointName + fi + done + + if [ -z ${PingSuccess} ]; then + EXIT_VAL=1 + echo "+++++++==ERROR==ERROR=============================================================================+++++" + echo "NSC ${nsc} failed to connect to the desired ${endpointName} NetworkService" + kubectl get pod "${nsc}" -o wide + echo "POD ${nsc} Network dump -------------------------------" + kubectl exec -ti "${nsc}" -- ip addr + kubectl exec -ti "${nsc}" ip route + echo "+++++++==ERROR==ERROR=============================================================================+++++" + fi + unset PingSuccess + done +done +exit ${EXIT_VAL} \ No newline at end of file diff --git a/examples/4g-spgw/sidecar-nse/Dockerfile b/examples/4g-spgw/sidecar-nse/Dockerfile new file mode 100644 index 0000000..0b20b7c --- /dev/null +++ b/examples/4g-spgw/sidecar-nse/Dockerfile @@ -0,0 +1,15 @@ +FROM golang:alpine as build +RUN apk --no-cache add git +ENV PACKAGEPATH=github.com/networkservicemesh/networkservicemesh/ +ENV GO111MODULE=on + +RUN mkdir /root/networkservicemesh +ADD ["go.mod","/root/networkservicemesh"] +WORKDIR /root/networkservicemesh/ +RUN go mod download + +ADD [".","/root/networkservicemesh"] +RUN CGO_ENABLED=0 GOOS=linux go build -ldflags '-extldflags "-static"' -o /go/bin/sidecar-nse ./examples/4g-spgw/sidecar-nse/cmd/ +FROM alpine as runtime +COPY --from=build /go/bin/sidecar-nse /bin/sidecar-nse +ENTRYPOINT ["/bin/sidecar-nse"] diff --git a/examples/4g-spgw/sidecar-nse/cmd/ifname.go b/examples/4g-spgw/sidecar-nse/cmd/ifname.go new file mode 100644 index 0000000..1905665 --- /dev/null +++ b/examples/4g-spgw/sidecar-nse/cmd/ifname.go @@ -0,0 +1,89 @@ +// Copyright 2020 VMware, Inc. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "strconv" + + "github.com/golang/protobuf/ptypes/empty" + "github.com/networkservicemesh/networkservicemesh/controlplane/api/connection" + mechanism "github.com/networkservicemesh/networkservicemesh/controlplane/api/connection/mechanisms/common" + "github.com/networkservicemesh/networkservicemesh/controlplane/api/networkservice" + "github.com/networkservicemesh/networkservicemesh/sdk/endpoint" + "github.com/pkg/errors" +) + +const ( + interfaceNameKey = mechanism.InterfaceNameKey + maxInterfaces = 10000 +) + +// InterfaceNameEndpoint is an endpoint that +type InterfaceNameEndpoint struct { + Names map[string]int +} + +// Request implements Request method from NetworkServiceServer +// Consumes from ctx context.Context: +// Next +func (ine *InterfaceNameEndpoint) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*connection.Connection, error) { + + if interfaceName, ok := request.GetRequestConnection().GetLabels()[interfaceNameKey]; ok { + c := request.GetConnection() + if _, ok := ine.Names[interfaceName]; !ok { + ine.Names[interfaceNameKey] = 0 + } else { + count := ine.Names[interfaceNameKey] + 1 + if count > maxInterfaces { + return nil, errors.Errorf("Reached the max interface count for %s", interfaceName) + } + ine.Names[interfaceNameKey] = count + interfaceName = interfaceName + strconv.Itoa(count) + } + endpoint.Log(ctx).Infof("Setting interface name to %s", interfaceName) + c.Mechanism.Parameters[mechanism.InterfaceNameKey] = interfaceName + } + + if endpoint.Next(ctx) != nil { + return endpoint.Next(ctx).Request(ctx, request) + } + + endpoint.Log(ctx).Infof("%v endpoint completed on connection: %v", ine.Name(), request.GetConnection()) + return request.GetConnection(), nil +} + +// Close implements Close method from NetworkServiceServer +// Consumes from ctx context.Context: +// Next +func (ine *InterfaceNameEndpoint) Close(ctx context.Context, connection *connection.Connection) (*empty.Empty, error) { + if endpoint.Next(ctx) != nil { + return endpoint.Next(ctx).Close(ctx, connection) + } + return &empty.Empty{}, nil +} + +// Name returns the composite name +func (ine *InterfaceNameEndpoint) Name() string { + return "InterfaceName" +} + +// NewInterfaceNameEndpoint create InterfaceNameEndpoint +func NewInterfaceNameEndpoint() *InterfaceNameEndpoint { + return &InterfaceNameEndpoint{ + Names: map[string]int{}, + } +} diff --git a/examples/4g-spgw/sidecar-nse/cmd/main.go b/examples/4g-spgw/sidecar-nse/cmd/main.go new file mode 100644 index 0000000..9f2ff04 --- /dev/null +++ b/examples/4g-spgw/sidecar-nse/cmd/main.go @@ -0,0 +1,55 @@ +// Copyright 2020 VMware, Inc. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + + "github.com/networkservicemesh/networkservicemesh/pkg/tools" + "github.com/networkservicemesh/networkservicemesh/sdk/common" + "github.com/networkservicemesh/networkservicemesh/sdk/endpoint" + "github.com/sirupsen/logrus" +) + +func main() { + // Capture signals to cleanup before exiting + c := tools.NewOSSignalChannel() + + configuration := common.FromEnv() + composite := endpoint.NewCompositeEndpoint( + endpoint.NewMonitorEndpoint(configuration), + endpoint.NewConnectionEndpoint(configuration), + endpoint.NewIpamEndpoint(configuration), + NewInterfaceNameEndpoint(), + ) + + clientApp := newNSMClientApp(common.FromEnv()) + clientApp.Run() + + nsmEndpoint, err := endpoint.NewNSMEndpoint(context.Background(), configuration, composite) + if err != nil { + logrus.Fatalf("%v", err) + } + + if err := nsmEndpoint.Start(); err != nil { + logrus.Fatalf("Unable to start the endpoint: %v", err) + } + + defer func() { _ = nsmEndpoint.Delete() }() + + // Capture signals to cleanup before exiting + <-c +} diff --git a/examples/4g-spgw/sidecar-nse/cmd/nsc-sidecar.go b/examples/4g-spgw/sidecar-nse/cmd/nsc-sidecar.go new file mode 100644 index 0000000..3c91a1d --- /dev/null +++ b/examples/4g-spgw/sidecar-nse/cmd/nsc-sidecar.go @@ -0,0 +1,93 @@ +// Copyright 2020 VMware, Inc. +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + + "github.com/networkservicemesh/networkservicemesh/controlplane/api/connection/mechanisms/kernel" + "github.com/networkservicemesh/networkservicemesh/pkg/tools" + "github.com/networkservicemesh/networkservicemesh/pkg/tools/spanhelper" + + "github.com/sirupsen/logrus" + + "github.com/networkservicemesh/networkservicemesh/pkg/tools/jaeger" + + "github.com/networkservicemesh/networkservicemesh/sdk/common" + + "github.com/networkservicemesh/networkservicemesh/sdk/client" +) + +type nsmClientApp struct { + configuration *common.NSConfiguration +} + +func (c *nsmClientApp) Run() { + closer := jaeger.InitJaeger("nsm-init") + + defer func() { _ = closer.Close() }() + + span := spanhelper.FromContext(context.Background(), "RequestNetworkService") + + defer span.Finish() + + c.configuration = c.configuration.FromEnv() + + if c.configuration.PodName == "" { + podName, err := tools.GetCurrentPodNameFromHostname() + if err != nil { + logrus.Infof("failed to get current pod name from hostname: %v", err) + } else { + c.configuration.PodName = podName + } + } + + if c.configuration.Namespace == "" { + c.configuration.Namespace = common.GetNamespace() + } + + clientList, err := client.NewNSMClientList(span.Context(), c.configuration) + if err != nil { + span.Finish() + + _ = closer.Close() + + logrus.Errorf("nsm client: Unable to create the NSM client %v", err) + + return + } + + err = clientList.ConnectRetry(span.Context(), "nsm", kernel.MECHANISM, + "Primary interface", client.ConnectionRetry, client.RequestDelay) + if err != nil { + span.Finish() + + _ = closer.Close() + + logrus.Errorf("nsm client: Unable to establish connection with network service") + + return + } + + logrus.Info("nsm client: initialization is completed successfully") + +} + +func newNSMClientApp(configration *common.NSConfiguration) *nsmClientApp { + return &nsmClientApp{ + configuration: configration, + } +} diff --git a/examples/4g-spgw/sidecar-nse/cmd/runner.go b/examples/4g-spgw/sidecar-nse/cmd/runner.go new file mode 100644 index 0000000..cfb3e61 --- /dev/null +++ b/examples/4g-spgw/sidecar-nse/cmd/runner.go @@ -0,0 +1,68 @@ +package main + +import ( + "context" + + "github.com/golang/protobuf/ptypes/empty" + "github.com/networkservicemesh/networkservicemesh/controlplane/api/connection" + "github.com/networkservicemesh/networkservicemesh/controlplane/api/networkservice" + "github.com/networkservicemesh/networkservicemesh/sdk/endpoint" +) + +// RunnerEndpoint is an endpoint that +type RunnerEndpoint struct { + script string + connections map[string]connection.Connection +} + +// Request implements Request method from NetworkServiceServer +// Consumes from ctx context.Context: +// Next +func (ine *RunnerEndpoint) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*connection.Connection, error) { + + // if interfaceName, ok := request.GetRequestConnection().GetLabels()[interfaceNameKey]; ok { + // c := request.GetConnection() + // if _, ok := ine.Names[interfaceName]; !ok { + // ine.Names[interfaceNameKey] = 0 + // } else { + // count := ine.Names[interfaceNameKey] + 1 + // if count > maxInterfaces { + // return nil, errors.Errorf("Reached the max interface count for %s", interfaceName) + // } + // ine.Names[interfaceNameKey] = count + // interfaceName = interfaceName + strconv.Itoa(count) + // } + // endpoint.Log(ctx).Infof("Setting interface name to %s", interfaceName) + // c.Mechanism.Parameters[mechanism.InterfaceNameKey] = interfaceName + // } + + if endpoint.Next(ctx) != nil { + return endpoint.Next(ctx).Request(ctx, request) + } + + endpoint.Log(ctx).Infof("%v endpoint completed on connection: %v", ine.Name(), request.GetConnection()) + return request.GetConnection(), nil +} + +// Close implements Close method from NetworkServiceServer +// Consumes from ctx context.Context: +// Next +func (ine *RunnerEndpoint) Close(ctx context.Context, connection *connection.Connection) (*empty.Empty, error) { + if endpoint.Next(ctx) != nil { + return endpoint.Next(ctx).Close(ctx, connection) + } + return &empty.Empty{}, nil +} + +// Name returns the composite name +func (ine *RunnerEndpoint) Name() string { + return "InterfaceName" +} + +// NewRunnerEndpoint create RunnerEndpoint +func NewRunnerEndpoint(script string) *RunnerEndpoint { + return &RunnerEndpoint{ + script: script, + connections: map[string]connection.Connection{}, + } +}