Skip to content

Commit 8a2b90e

Browse files
committed
Refactor: use p4runtime_lib instead of external dependency, self-contained veth setup, add make test target to the Makerfile, updated the README.md to reflect changes
Signed-off-by: aqn96 <aqnguyen96@gmail.com> Signed-off-by: An <aqnguyen96@gmail.com>
1 parent ec5d91a commit 8a2b90e

File tree

4 files changed

+86
-37
lines changed

4 files changed

+86
-37
lines changed

exercises/basic/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@ BMV2_SWITCH_EXE = simple_switch_grpc
33
TOPO = pod-topo/topology.json
44

55
include ../../utils/Makefile
6+
7+
test:
8+
./runptf.sh

exercises/basic/README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,11 @@ forwarding, and multi-entry LPM routing.
198198

199199
To run the tests:
200200
```bash
201-
./runptf.sh
201+
make test
202202
```
203203

204-
Note: The `veth` interfaces must be set up before running. If you see
205-
a "No such device" error, run the `veth_setup.sh` script from
206-
[p4-guide](https://github.com/jafingerhut/p4-guide/blob/master/bin/veth_setup.sh).
204+
This handles veth interface creation, P4 compilation, switch startup,
205+
test execution, and cleanup automatically.
207206

208207
## Relevant Documentation
209208

exercises/basic/ptf/basic_fwd.py

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,20 @@
1515
# limitations under the License.
1616

1717
import logging
18+
import os
19+
import sys
1820

1921
import ptf
2022
import ptf.testutils as tu
2123
from ptf.base_tests import BaseTest
22-
import p4runtime_sh.shell as sh
23-
import p4runtime_shell_utils as shu
24+
25+
# Import p4runtime_lib from the tutorials repo utils directory
26+
sys.path.append(
27+
os.path.join(os.path.dirname(os.path.abspath(__file__)),
28+
'../../../utils/'))
29+
import p4runtime_lib.bmv2
30+
import p4runtime_lib.helper
31+
from p4runtime_lib.switch import ShutdownAllSwitchConnections
2432

2533

2634
# Configure logging
@@ -38,32 +46,53 @@ def setUp(self):
3846
self.dataplane.flush()
3947

4048
logging.debug("BasicFwdTest.setUp()")
49+
50+
# Get test parameters
4151
grpc_addr = tu.test_param_get("grpcaddr")
4252
if grpc_addr is None:
4353
grpc_addr = 'localhost:9559'
4454
p4info_txt_fname = tu.test_param_get("p4info")
4555
p4prog_binary_fname = tu.test_param_get("config")
46-
sh.setup(device_id=0,
47-
grpc_addr=grpc_addr,
48-
election_id=(0, 1),
49-
config=sh.FwdPipeConfig(p4info_txt_fname, p4prog_binary_fname),
50-
verbose=False)
56+
57+
# Create P4Info helper for building table entries
58+
self.p4info_helper = p4runtime_lib.helper.P4InfoHelper(p4info_txt_fname)
59+
60+
# Connect to the switch via gRPC
61+
self.sw = p4runtime_lib.bmv2.Bmv2SwitchConnection(
62+
name='s1',
63+
address=grpc_addr,
64+
device_id=0,
65+
proto_dump_file='logs/s1-p4runtime-requests.txt')
66+
67+
# Establish as master controller
68+
self.sw.MasterArbitrationUpdate()
69+
70+
# Load the P4 program onto the switch
71+
self.sw.SetForwardingPipelineConfig(
72+
p4info=self.p4info_helper.p4info,
73+
bmv2_json_file_path=p4prog_binary_fname)
5174

5275
def tearDown(self):
5376
logging.debug("BasicFwdTest.tearDown()")
54-
sh.teardown()
77+
ShutdownAllSwitchConnections()
5578

5679

5780
######################################################################
5881
# Helper function to add entries to ipv4_lpm table
5982
######################################################################
6083

61-
def add_ipv4_lpm_entry(ipv4_addr_str, prefix_len, dst_mac_str, port):
62-
te = sh.TableEntry('MyIngress.ipv4_lpm')(action='MyIngress.ipv4_forward')
63-
te.match['hdr.ipv4.dstAddr'] = '%s/%d' % (ipv4_addr_str, prefix_len)
64-
te.action['dstAddr'] = dst_mac_str
65-
te.action['port'] = '%d' % port
66-
te.insert()
84+
def add_ipv4_lpm_entry(self, ipv4_addr_str, prefix_len, dst_mac_str, port):
85+
table_entry = self.p4info_helper.buildTableEntry(
86+
table_name='MyIngress.ipv4_lpm',
87+
match_fields={
88+
'hdr.ipv4.dstAddr': (ipv4_addr_str, prefix_len)
89+
},
90+
action_name='MyIngress.ipv4_forward',
91+
action_params={
92+
'dstAddr': dst_mac_str,
93+
'port': port
94+
})
95+
self.sw.WriteTableEntry(table_entry)
6796

6897

6998
class DropTest(BasicFwdTest):
@@ -92,7 +121,7 @@ def runTest(self):
92121
out_dmac = '08:00:00:00:02:22'
93122

94123
# Add a forwarding entry
95-
add_ipv4_lpm_entry(ip_dst, 32, out_dmac, eg_port)
124+
self.add_ipv4_lpm_entry(ip_dst, 32, out_dmac, eg_port)
96125

97126
# Send packet
98127
pkt = tu.simple_tcp_packet(eth_src=in_smac, eth_dst=in_dmac,
@@ -131,8 +160,8 @@ def runTest(self):
131160

132161
# Add all entries
133162
for e in entries:
134-
add_ipv4_lpm_entry(e['ip_dst'], e['prefix_len'],
135-
e['out_dmac'], e['eg_port'])
163+
self.add_ipv4_lpm_entry(e['ip_dst'], e['prefix_len'],
164+
e['out_dmac'], e['eg_port'])
136165

137166
# Test each entry
138167
ttl_in = 64

exercises/basic/runptf.sh

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,25 @@
22
# Run PTF tests for the basic forwarding exercise.
33
# Tests run against the solution P4 program.
44

5-
# Path to p4runtime_shell_utils and testlib
6-
T="`realpath ~/p4-guide/testlib`"
7-
if [ x"${PYTHONPATH}" == "x" ]
8-
then
9-
P="${T}"
10-
else
11-
P="${T}:${PYTHONPATH}"
12-
fi
5+
set -e
6+
7+
# ---- veth setup ----
8+
echo "Creating veth interfaces..."
9+
for i in 0 1 2 3 4 5 6 7; do
10+
intf0="veth$(( i * 2 ))"
11+
intf1="veth$(( i * 2 + 1 ))"
12+
if ! ip link show $intf0 &>/dev/null; then
13+
sudo ip link add name $intf0 type veth peer name $intf1
14+
sudo ip link set dev $intf0 up
15+
sudo ip link set dev $intf1 up
16+
sudo sysctl -q net.ipv6.conf.$intf0.disable_ipv6=1
17+
sudo sysctl -q net.ipv6.conf.$intf1.disable_ipv6=1
18+
fi
19+
done
1320

1421
set -x
1522

16-
# Compile the solution P4 program into build directory
23+
# ---- compile ----
1724
mkdir -p build
1825
p4c --target bmv2 \
1926
--arch v1model \
@@ -23,7 +30,7 @@ p4c --target bmv2 \
2330

2431
/bin/rm -f ss-log.txt
2532

26-
# Start simple_switch_grpc with no P4 program loaded (loaded via P4Runtime)
33+
# ---- start switch ----
2734
sudo simple_switch_grpc \
2835
--log-file ss-log \
2936
--log-flush \
@@ -39,12 +46,11 @@ sudo simple_switch_grpc \
3946
--no-p4 &
4047

4148
echo ""
42-
echo "Started simple_switch_grpc. Waiting 2 seconds before starting PTF test ..."
49+
echo "Started simple_switch_grpc. Waiting 2 seconds before starting PTF test..."
4350
sleep 2
4451

45-
# Run PTF tests
52+
# ---- run tests ----
4653
sudo ${P4_EXTRA_SUDO_OPTS} `which ptf` \
47-
--pypath "$P" \
4854
-i 0@veth1 \
4955
-i 1@veth3 \
5056
-i 2@veth5 \
@@ -57,10 +63,22 @@ sudo ${P4_EXTRA_SUDO_OPTS} `which ptf` \
5763
--test-dir ptf
5864

5965
echo ""
60-
echo "PTF test finished. Waiting 2 seconds before killing simple_switch_grpc ..."
66+
echo "PTF test finished. Waiting 2 seconds before killing simple_switch_grpc..."
6167
sleep 2
68+
69+
# ---- cleanup ----
6270
sudo pkill --signal 9 --list-name simple_switch
71+
6372
echo ""
64-
echo "Verifying that there are no simple_switch_grpc processes running any longer in 4 seconds ..."
65-
sleep 4
73+
echo "Cleaning up veth interfaces..."
74+
for i in 0 1 2 3 4 5 6 7; do
75+
intf0="veth$(( i * 2 ))"
76+
if ip link show $intf0 &>/dev/null; then
77+
sudo ip link del $intf0
78+
fi
79+
done
80+
81+
echo ""
82+
echo "Verifying no simple_switch_grpc processes remain..."
83+
sleep 2
6684
ps axguwww | grep simple_switch

0 commit comments

Comments
 (0)