Skip to content

Commit

Permalink
Add EXERCISE 8 on GTP termination with fabric.p4 (#47)
Browse files Browse the repository at this point in the history
* Use custom stratum_bmv2 image for both mininet and ptf

This is required to use scapy in Mininet. Before the ptf image was
essentially mn-stratum plus scapy, ptf, etc. I renamed that to a generic
stratum_bmv2 and use it for both mininet  (in docker-compose) and to run
ptf tests, instead of using two different images.

* Progress on exercise 8

* Bump stratum_bmv2

* Fix loop by disabling ip4 forwarding

Perhaps it is enabled by default in Docker for Mac?

* Fix flowrule-gtp.json solution

* Add make targets to push flow rules

* Check gtp solution in Travis

* Add instructions for Exercise 8

* Not exercise 4

* Update topo img

* Edits

* Add link to main readme
  • Loading branch information
ccascone authored Jun 2, 2020
1 parent 0702ca2 commit e1cbf1a
Show file tree
Hide file tree
Showing 17 changed files with 1,023 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ install:
- make deps

script:
- make check check-sr NGSDN_TUTORIAL_SUDO=sudo
- make check check-sr check-gtp NGSDN_TUTORIAL_SUDO=sudo
7 changes: 5 additions & 2 deletions EXERCISE-7.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ Re-start ONOS and Mininet, this time with the new IPv4 topology:

$ make start-v4

Wait about 1 minute before proceeding with the next steps, this will give time
to ONOS to start all of its subsystems.

### 2. Load fabric pipeconf and segmentrouting

Differently from previous exercises, instead of building and installing our own
Expand Down Expand Up @@ -596,6 +599,6 @@ forwarding in a 2x2 leaf-spine fabric of IPv4 hosts.
[netcfg.json]: mininet/netcfg.json
[docker-compose.yml]: docker-compose.yml
[pseudo-wire]: https://en.wikipedia.org/wiki/Pseudo-wire
[onos/apps/segmentrouting]: https://github.com/opennetworkinglab/onos/tree/onos-2.2/apps/segmentrouting
[onos/pipelines/fabric]: https://github.com/opennetworkinglab/onos/tree/onos-2.2/pipelines/fabric
[onos/apps/segmentrouting]: https://github.com/opennetworkinglab/onos/tree/2.2.2/apps/segmentrouting
[onos/pipelines/fabric]: https://github.com/opennetworkinglab/onos/tree/2.2.2/pipelines/fabric
[fabric-tofino]: https://github.com/opencord/fabric-tofino
451 changes: 451 additions & 0 deletions EXERCISE-8.md

Large diffs are not rendered by default.

52 changes: 44 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@ _docker_pull_all:
docker tag ${P4RT_SH_IMG}@${P4RT_SH_SHA} ${P4RT_SH_IMG}
docker pull ${P4C_IMG}@${P4C_SHA}
docker tag ${P4C_IMG}@${P4C_SHA} ${P4C_IMG}
docker pull ${MN_STRATUM_IMG}@${MN_STRATUM_SHA}
docker tag ${MN_STRATUM_IMG}@${MN_STRATUM_SHA} ${MN_STRATUM_IMG}
docker pull ${STRATUM_BMV2_IMG}@${STRATUM_BMV2_SHA}
docker tag ${STRATUM_BMV2_IMG}@${STRATUM_BMV2_SHA} ${STRATUM_BMV2_IMG}
docker pull ${MVN_IMG}@${MVN_SHA}
docker tag ${MVN_IMG}@${MVN_SHA} ${MVN_IMG}
docker pull ${PTF_IMG}@${PTF_SHA}
docker tag ${PTF_IMG}@${PTF_SHA} ${PTF_IMG}
docker pull ${GNMI_CLI_IMG}@${GNMI_CLI_SHA}
docker tag ${GNMI_CLI_IMG}@${GNMI_CLI_SHA} ${GNMI_CLI_IMG}
docker pull ${YANG_IMG}@${YANG_SHA}
Expand All @@ -45,6 +43,9 @@ start: _start
start-v4: NGSDN_TOPO_PY := topo-v4.py
start-v4: _start

start-gtp: NGSDN_TOPO_PY := topo-gtp.py
start-gtp: _start

stop:
$(info *** Stopping ONOS and Mininet...)
@NGSDN_TOPO_PY=foo docker-compose down -t0
Expand Down Expand Up @@ -82,6 +83,21 @@ netcfg: _netcfg
netcfg-sr: NGSDN_NETCFG_JSON := netcfg-sr.json
netcfg-sr: _netcfg

netcfg-gtp: NGSDN_NETCFG_JSON := netcfg-gtp.json
netcfg-gtp: _netcfg

flowrule-gtp:
$(info *** Pushing flowrule-gtp.json to ONOS...)
${onos_curl} -X POST -H 'Content-Type:application/json' \
${onos_url}/v1/flows?appId=rest-api -d@./mininet/flowrule-gtp.json
@echo

flowrule-clean:
$(info *** Removing all flows installed via REST APIs...)
${onos_curl} -X DELETE -H 'Content-Type:application/json' \
${onos_url}/v1/flows/application/rest-api
@echo

reset: stop
-$(NGSDN_TUTORIAL_SUDO) rm -rf ./tmp

Expand All @@ -101,7 +117,7 @@ p4-build: p4src/main.p4
@echo "*** P4 program compiled successfully! Output files are in p4src/build"

p4-test:
@cd ptf && PTF_DOCKER_IMG=$(PTF_IMG) ./run_tests $(TEST)
@cd ptf && PTF_DOCKER_IMG=$(STRATUM_BMV2_IMG) ./run_tests $(TEST)

_copy_p4c_out:
$(info *** Copying p4c outputs to app resources...)
Expand Down Expand Up @@ -132,9 +148,6 @@ app-uninstall:

app-reload: app-uninstall app-install

mn-single:
docker run --privileged --rm -it -v /tmp/mn-stratum:/tmp -p 50001:50001 ${MN_STRATUM_IMG}

yang-tools:
docker run --rm -it -v ${curr_dir}/yang/demo-port.yang:/models/demo-port.yang ${YANG_IMG}

Expand All @@ -147,6 +160,7 @@ solution-apply:
rsync -r solution/ ./

solution-revert:
test -d working_copy
$(NGSDN_TUTORIAL_SUDO) rm -rf ./app/*
$(NGSDN_TUTORIAL_SUDO) rm -rf ./p4src/*
$(NGSDN_TUTORIAL_SUDO) rm -rf ./ptf/*
Expand Down Expand Up @@ -229,3 +243,25 @@ check-sr:
util/mn-cmd h4 ping -c 1 172.16.2.1
make stop
make solution-revert

check-gtp:
make reset
make start-gtp
sleep 45
util/onos-cmd app activate segmentrouting
util/onos-cmd app activate pipelines.fabric
util/onos-cmd app activate netcfghostprovider
sleep 15
make solution-apply
make netcfg-gtp
sleep 20
util/mn-cmd enodeb ping -c 1 10.0.100.254
util/mn-cmd pdn ping -c 1 10.0.200.254
util/onos-cmd route-add 17.0.0.0/24 10.0.100.1
make flowrule-gtp
# util/mn-cmd requires a TTY because it uses docker -it option
# hence we use screen for putting it in the background
screen -d -m util/mn-cmd pdn /mininet/send-udp.py
util/mn-cmd enodeb /mininet/recv-gtp.py -e
make stop
make solution-revert
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ Click on the exercise name to see the instructions:
4. [Enabling ONOS built-in services](./EXERCISE-4.md)
5. [Implementing IPv6 routing with ECMP](./EXERCISE-5.md)
6. [Implementing SRv6](./EXERCISE-6.md)
6. [Trellis Basics](./EXERCISE-7.md)
7. [Trellis Basics](./EXERCISE-7.md)
8. [GTP termination with fabric.p4](./EXERCISE-8.md)

## Solutions

Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: "3"

services:
mininet:
image: opennetworking/mn-stratum
image: opennetworking/ngsdn-tutorial:stratum_bmv2
hostname: mininet
container_name: mininet
privileged: true
Expand Down
Binary file added img/topo-gtp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 33 additions & 0 deletions mininet/flowrule-gtp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"flows": [
{
"deviceId": "device:leaf1",
"tableId": "FabricIngress.spgw_ingress.dl_sess_lookup",
"priority": 10,
"timeout": 0,
"isPermanent": true,
"selector": {
"criteria": [
{
"type": "IPV4_DST",
"ip": "<INSERT UE IP ADDRESS HERE>/32"
}
]
},
"treatment": {
"instructions": [
{
"type": "PROTOCOL_INDEPENDENT",
"subtype": "ACTION",
"actionId": "FabricIngress.spgw_ingress.set_dl_sess_info",
"actionParams": {
"teid": "BEEF",
"s1u_enb_addr": "0a006401",
"s1u_sgw_addr": "0a0064fe"
}
}
]
}
}
]
}
130 changes: 130 additions & 0 deletions mininet/netcfg-gtp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
{
"devices": {
"device:leaf1": {
"basic": {
"managementAddress": "grpc://mininet:50001?device_id=1",
"driver": "stratum-bmv2",
"pipeconf": "org.onosproject.pipelines.fabric",
"locType": "grid",
"gridX": 200,
"gridY": 600
},
"segmentrouting": {
"name": "leaf1",
"ipv4NodeSid": 101,
"ipv4Loopback": "192.168.1.1",
"routerMac": "00:AA:00:00:00:01",
"isEdgeRouter": true,
"adjacencySids": []
}
},
"device:leaf2": {
"basic": {
"managementAddress": "grpc://mininet:50002?device_id=1",
"driver": "stratum-bmv2",
"pipeconf": "org.onosproject.pipelines.fabric",
"locType": "grid",
"gridX": 800,
"gridY": 600
},
"segmentrouting": {
"name": "leaf2",
"ipv4NodeSid": 102,
"ipv4Loopback": "192.168.1.2",
"routerMac": "00:AA:00:00:00:02",
"isEdgeRouter": true,
"adjacencySids": []
}
},
"device:spine1": {
"basic": {
"managementAddress": "grpc://mininet:50003?device_id=1",
"driver": "stratum-bmv2",
"pipeconf": "org.onosproject.pipelines.fabric",
"locType": "grid",
"gridX": 400,
"gridY": 400
},
"segmentrouting": {
"name": "spine1",
"ipv4NodeSid": 201,
"ipv4Loopback": "192.168.2.1",
"routerMac": "00:BB:00:00:00:01",
"isEdgeRouter": false,
"adjacencySids": []
}
},
"device:spine2": {
"basic": {
"managementAddress": "grpc://mininet:50004?device_id=1",
"driver": "stratum-bmv2",
"pipeconf": "org.onosproject.pipelines.fabric",
"locType": "grid",
"gridX": 600,
"gridY": 400
},
"segmentrouting": {
"name": "spine2",
"ipv4NodeSid": 202,
"ipv4Loopback": "192.168.2.2",
"routerMac": "00:BB:00:00:00:02",
"isEdgeRouter": false,
"adjacencySids": []
}
}
},
"ports": {
"device:leaf1/3": {
"interfaces": [
{
"name": "leaf1-3",
"ips": [
"10.0.100.254/24"
],
"vlan-untagged": 100
}
]
},
"device:leaf2/3": {
"interfaces": [
{
"name": "leaf2-3",
"ips": [
"10.0.200.254/24"
],
"vlan-untagged": 200
}
]
}
},
"hosts": {
"00:00:00:00:00:10/None": {
"basic": {
"name": "enodeb",
"gridX": 100,
"gridY": 700,
"locType": "grid",
"ips": [
"10.0.100.1"
],
"locations": [
"device:leaf1/3"
]
}
},
"00:00:00:00:00:20/None": {
"basic": {
"name": "pdn",
"gridX": 850,
"gridY": 700,
"locType": "grid",
"ips": [
"10.0.200.1"
],
"locations": [
"device:leaf2/3"
]
}
}
}
}
48 changes: 48 additions & 0 deletions mininet/recv-gtp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/python

# Script used in Exercise 8 that sniffs packets and prints on screen whether
# they are GTP encapsulated or not.

import signal
import sys

from ptf.packet import IP
from scapy.contrib import gtp
from scapy.sendrecv import sniff

pkt_count = 0


def handle_pkt(pkt, ex):
global pkt_count
pkt_count = pkt_count + 1
if gtp.GTP_U_Header in pkt:
is_gtp_encap = True
else:
is_gtp_encap = False

print "[%d] %d bytes: %s -> %s, is_gtp_encap=%s\n\t%s" \
% (pkt_count, len(pkt), pkt[IP].src, pkt[IP].dst,
is_gtp_encap, pkt.summary())

if is_gtp_encap and ex:
exit()


print "Will print a line for each UDP packet received..."


def handle_timeout(signum, frame):
print "Timeout! Did not receive any GTP packet"
exit(1)


exitOnSuccess = False
if len(sys.argv) > 1 and sys.argv[1] == "-e":
# wait max 10 seconds or exit
signal.signal(signal.SIGALRM, handle_timeout)
signal.alarm(10)
exitOnSuccess = True

sniff(count=0, store=False, filter="udp",
prn=lambda x: handle_pkt(x, exitOnSuccess))
16 changes: 16 additions & 0 deletions mininet/send-udp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/python

# Script used in Exercise 8.
# Send downlink packets to UE address.

from scapy.layers.inet import IP, UDP
from scapy.sendrecv import send

UE_ADDR = '17.0.0.1'
RATE = 5 # packets per second
PAYLOAD = ' '.join(['P4 is great!'] * 50)

print "Sending %d UDP packets per second to %s..." % (RATE, UE_ADDR)

pkt = IP(dst=UE_ADDR) / UDP(sport=80, dport=400) / PAYLOAD
send(pkt, inter=1.0 / RATE, loop=True, verbose=True)
Loading

0 comments on commit e1cbf1a

Please sign in to comment.