parent
08445e0b18
commit
948a890700
@ -9,8 +9,8 @@ you get started with P4 programming, organized into several modules:
|
||||
* [Basic Forwarding](./exercises/basic)
|
||||
* [Basic Tunneling](./exercises/basic_tunnel)
|
||||
|
||||
2. P4 Runtime and the Control Plane
|
||||
* [P4 Runtime](./exercises/p4runtime)
|
||||
2. P4Runtime and the Control Plane
|
||||
* [P4Runtime](./exercises/p4runtime)
|
||||
|
||||
3. Monitoring and Debugging
|
||||
* [Explicit Congestion Notification](./exercises/ecn)
|
||||
|
@ -1,8 +1,8 @@
|
||||
# Implementing a Control Plane using P4 Runtime
|
||||
# Implementing a Control Plane using P4Runtime
|
||||
|
||||
## Introduction
|
||||
|
||||
In this exercise, we will be using P4 Runtime to send flow entries to the
|
||||
In this exercise, we will be using P4Runtime to send flow entries to the
|
||||
switch instead of using the switch's CLI. We will be building on the same P4
|
||||
program that you used in the [basic_tunnel](../basic_tunnel) exercise. The
|
||||
P4 program has been renamed to `advanced_tunnel.py` and has been augmented
|
||||
@ -94,14 +94,14 @@ table entries like we have in the previous exercises.
|
||||
switch pipeline and control plane. This interface is defined in the
|
||||
`advanced_tunnel.p4info` file. The table entries that you build in `mycontroller.py`
|
||||
refer to specific tables, keys, and actions by name, and we use a P4Info helper
|
||||
to convert the names into the IDs that are required for P4 Runtime. Any changes
|
||||
to convert the names into the IDs that are required for P4Runtime. Any changes
|
||||
in the P4 program that add or rename tables, keys, or actions will need to be
|
||||
reflected in your table entries.
|
||||
|
||||
## Step 2: Implement Tunnel Forwarding
|
||||
|
||||
The `mycontroller.py` file is a basic controller plane that does the following:
|
||||
1. Establishes a gRPC connection to the switches for the P4 Runtime service.
|
||||
1. Establishes a gRPC connection to the switches for the P4Runtime service.
|
||||
2. Pushes the P4 program to each switch.
|
||||
3. Writes tunnel ingress and tunnel egress rules for two tunnels between h1 and h2.
|
||||
4. Reads tunnel ingress and egress counters every 2 seconds.
|
||||
@ -119,12 +119,12 @@ the `p4runtime_lib` directory. Here is a summary of each of the files in the dir
|
||||
- `helper.py`
|
||||
- Contains the `P4InfoHelper` class which is used to parse the `p4info` files.
|
||||
- Provides translation methods from entity name to and from ID number.
|
||||
- Builds P4 program-dependent sections of P4 Runtime table entries.
|
||||
- Builds P4 program-dependent sections of P4Runtime table entries.
|
||||
- `switch.py`
|
||||
- Contains the `SwitchConnection` class which grabs the gRPC client stub, and
|
||||
establishes connections to the switches.
|
||||
- Provides helper methods that construct the P4 Runtime protocol buffer messages
|
||||
and makes the P4 Runtime gRPC service calls.
|
||||
- Provides helper methods that construct the P4Runtime protocol buffer messages
|
||||
and makes the P4Runtime gRPC service calls.
|
||||
- `bmv2.py`
|
||||
- Contains `Bmv2SwitchConnection` which extends `SwitchConnections` and provides
|
||||
the BMv2-specific device payload to load the P4 program.
|
||||
@ -161,8 +161,8 @@ need to change it for a more realistic network?
|
||||
Hint: The default TTL is 64 for packets sent by the hosts.
|
||||
|
||||
If you are interested, you can find the protocol buffer and gRPC definitions here:
|
||||
- [P4 Runtime](https://github.com/p4lang/PI/blob/master/proto/p4/p4runtime.proto)
|
||||
- [P4 Info](https://github.com/p4lang/PI/blob/master/proto/p4/config/p4info.proto)
|
||||
- [P4Runtime](https://github.com/p4lang/PI/blob/master/proto/p4/p4runtime.proto)
|
||||
- [P4Info](https://github.com/p4lang/PI/blob/master/proto/p4/config/p4info.proto)
|
||||
|
||||
#### Cleaning up Mininet
|
||||
|
||||
|
@ -133,12 +133,12 @@ def printGrpcError(e):
|
||||
print "[%s:%d]" % (traceback.tb_frame.f_code.co_filename, traceback.tb_lineno)
|
||||
|
||||
def main(p4info_file_path, bmv2_file_path):
|
||||
# Instantiate a P4 Runtime helper from the p4info file
|
||||
# Instantiate a P4Runtime helper from the p4info file
|
||||
p4info_helper = p4runtime_lib.helper.P4InfoHelper(p4info_file_path)
|
||||
|
||||
try:
|
||||
# Create a switch connection object for s1 and s2;
|
||||
# this is backed by a P4 Runtime gRPC connection.
|
||||
# this is backed by a P4Runtime gRPC connection.
|
||||
# Also, dump all P4Runtime messages sent to switch to given txt files.
|
||||
s1 = p4runtime_lib.bmv2.Bmv2SwitchConnection(
|
||||
name='s1',
|
||||
|
@ -145,11 +145,11 @@ def printCounter(p4info_helper, sw, counter_name, index):
|
||||
|
||||
|
||||
def main(p4info_file_path, bmv2_file_path):
|
||||
# Instantiate a P4 Runtime helper from the p4info file
|
||||
# Instantiate a P4Runtime helper from the p4info file
|
||||
p4info_helper = p4runtime_lib.helper.P4InfoHelper(p4info_file_path)
|
||||
|
||||
# Create a switch connection object for s1 and s2;
|
||||
# this is backed by a P4 Runtime gRPC connection.
|
||||
# this is backed by a P4Runtime gRPC connection.
|
||||
# Also, dump all P4Runtime messages sent to switch to given txt files.
|
||||
s1 = p4runtime_lib.bmv2.Bmv2SwitchConnection(
|
||||
name='s1',
|
||||
|
@ -62,7 +62,7 @@ class SwitchConnection(object):
|
||||
request.arbitration.election_id.low = 1
|
||||
|
||||
if dry_run:
|
||||
print "P4 Runtime MasterArbitrationUpdate: ", request
|
||||
print "P4Runtime MasterArbitrationUpdate: ", request
|
||||
else:
|
||||
self.requests_stream.put(request)
|
||||
|
||||
@ -78,7 +78,7 @@ class SwitchConnection(object):
|
||||
|
||||
request.action = p4runtime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_COMMIT
|
||||
if dry_run:
|
||||
print "P4 Runtime SetForwardingPipelineConfig:", request
|
||||
print "P4Runtime SetForwardingPipelineConfig:", request
|
||||
else:
|
||||
self.client_stub.SetForwardingPipelineConfig(request)
|
||||
|
||||
@ -90,7 +90,7 @@ class SwitchConnection(object):
|
||||
update.type = p4runtime_pb2.Update.INSERT
|
||||
update.entity.table_entry.CopyFrom(table_entry)
|
||||
if dry_run:
|
||||
print "P4 Runtime Write:", request
|
||||
print "P4Runtime Write:", request
|
||||
else:
|
||||
self.client_stub.Write(request)
|
||||
|
||||
@ -104,7 +104,7 @@ class SwitchConnection(object):
|
||||
else:
|
||||
table_entry.table_id = 0
|
||||
if dry_run:
|
||||
print "P4 Runtime Read:", request
|
||||
print "P4Runtime Read:", request
|
||||
else:
|
||||
for response in self.client_stub.Read(request):
|
||||
yield response
|
||||
@ -121,7 +121,7 @@ class SwitchConnection(object):
|
||||
if index is not None:
|
||||
counter_entry.index.index = index
|
||||
if dry_run:
|
||||
print "P4 Runtime Read:", request
|
||||
print "P4Runtime Read:", request
|
||||
else:
|
||||
for response in self.client_stub.Read(request):
|
||||
yield response
|
||||
|
@ -38,7 +38,7 @@ def configureP4Switch(**switch_args):
|
||||
switch's thrift server is using a unique port.
|
||||
"""
|
||||
if "sw_path" in switch_args and 'grpc' in switch_args['sw_path']:
|
||||
# If grpc appears in the BMv2 switch target, we assume will start P4 Runtime
|
||||
# If grpc appears in the BMv2 switch target, we assume will start P4Runtime
|
||||
class ConfiguredP4RuntimeSwitch(P4RuntimeSwitch):
|
||||
def __init__(self, *opts, **kwargs):
|
||||
kwargs.update(switch_args)
|
||||
|
Loading…
x
Reference in New Issue
Block a user