parent
08445e0b18
commit
948a890700
@ -9,8 +9,8 @@ you get started with P4 programming, organized into several modules:
|
|||||||
* [Basic Forwarding](./exercises/basic)
|
* [Basic Forwarding](./exercises/basic)
|
||||||
* [Basic Tunneling](./exercises/basic_tunnel)
|
* [Basic Tunneling](./exercises/basic_tunnel)
|
||||||
|
|
||||||
2. P4 Runtime and the Control Plane
|
2. P4Runtime and the Control Plane
|
||||||
* [P4 Runtime](./exercises/p4runtime)
|
* [P4Runtime](./exercises/p4runtime)
|
||||||
|
|
||||||
3. Monitoring and Debugging
|
3. Monitoring and Debugging
|
||||||
* [Explicit Congestion Notification](./exercises/ecn)
|
* [Explicit Congestion Notification](./exercises/ecn)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# Implementing a Control Plane using P4 Runtime
|
# Implementing a Control Plane using P4Runtime
|
||||||
|
|
||||||
## Introduction
|
## 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
|
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
|
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
|
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
|
switch pipeline and control plane. This interface is defined in the
|
||||||
`advanced_tunnel.p4info` file. The table entries that you build in `mycontroller.py`
|
`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
|
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
|
in the P4 program that add or rename tables, keys, or actions will need to be
|
||||||
reflected in your table entries.
|
reflected in your table entries.
|
||||||
|
|
||||||
## Step 2: Implement Tunnel Forwarding
|
## Step 2: Implement Tunnel Forwarding
|
||||||
|
|
||||||
The `mycontroller.py` file is a basic controller plane that does the following:
|
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.
|
2. Pushes the P4 program to each switch.
|
||||||
3. Writes tunnel ingress and tunnel egress rules for two tunnels between h1 and h2.
|
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.
|
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`
|
- `helper.py`
|
||||||
- Contains the `P4InfoHelper` class which is used to parse the `p4info` files.
|
- Contains the `P4InfoHelper` class which is used to parse the `p4info` files.
|
||||||
- Provides translation methods from entity name to and from ID number.
|
- 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`
|
- `switch.py`
|
||||||
- Contains the `SwitchConnection` class which grabs the gRPC client stub, and
|
- Contains the `SwitchConnection` class which grabs the gRPC client stub, and
|
||||||
establishes connections to the switches.
|
establishes connections to the switches.
|
||||||
- Provides helper methods that construct the P4 Runtime protocol buffer messages
|
- Provides helper methods that construct the P4Runtime protocol buffer messages
|
||||||
and makes the P4 Runtime gRPC service calls.
|
and makes the P4Runtime gRPC service calls.
|
||||||
- `bmv2.py`
|
- `bmv2.py`
|
||||||
- Contains `Bmv2SwitchConnection` which extends `SwitchConnections` and provides
|
- Contains `Bmv2SwitchConnection` which extends `SwitchConnections` and provides
|
||||||
the BMv2-specific device payload to load the P4 program.
|
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.
|
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:
|
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)
|
- [P4Runtime](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)
|
- [P4Info](https://github.com/p4lang/PI/blob/master/proto/p4/config/p4info.proto)
|
||||||
|
|
||||||
#### Cleaning up Mininet
|
#### Cleaning up Mininet
|
||||||
|
|
||||||
|
@ -133,12 +133,12 @@ def printGrpcError(e):
|
|||||||
print "[%s:%d]" % (traceback.tb_frame.f_code.co_filename, traceback.tb_lineno)
|
print "[%s:%d]" % (traceback.tb_frame.f_code.co_filename, traceback.tb_lineno)
|
||||||
|
|
||||||
def main(p4info_file_path, bmv2_file_path):
|
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)
|
p4info_helper = p4runtime_lib.helper.P4InfoHelper(p4info_file_path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Create a switch connection object for s1 and s2;
|
# 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.
|
# Also, dump all P4Runtime messages sent to switch to given txt files.
|
||||||
s1 = p4runtime_lib.bmv2.Bmv2SwitchConnection(
|
s1 = p4runtime_lib.bmv2.Bmv2SwitchConnection(
|
||||||
name='s1',
|
name='s1',
|
||||||
|
@ -145,11 +145,11 @@ def printCounter(p4info_helper, sw, counter_name, index):
|
|||||||
|
|
||||||
|
|
||||||
def main(p4info_file_path, bmv2_file_path):
|
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)
|
p4info_helper = p4runtime_lib.helper.P4InfoHelper(p4info_file_path)
|
||||||
|
|
||||||
# Create a switch connection object for s1 and s2;
|
# 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.
|
# Also, dump all P4Runtime messages sent to switch to given txt files.
|
||||||
s1 = p4runtime_lib.bmv2.Bmv2SwitchConnection(
|
s1 = p4runtime_lib.bmv2.Bmv2SwitchConnection(
|
||||||
name='s1',
|
name='s1',
|
||||||
|
@ -62,7 +62,7 @@ class SwitchConnection(object):
|
|||||||
request.arbitration.election_id.low = 1
|
request.arbitration.election_id.low = 1
|
||||||
|
|
||||||
if dry_run:
|
if dry_run:
|
||||||
print "P4 Runtime MasterArbitrationUpdate: ", request
|
print "P4Runtime MasterArbitrationUpdate: ", request
|
||||||
else:
|
else:
|
||||||
self.requests_stream.put(request)
|
self.requests_stream.put(request)
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ class SwitchConnection(object):
|
|||||||
|
|
||||||
request.action = p4runtime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_COMMIT
|
request.action = p4runtime_pb2.SetForwardingPipelineConfigRequest.VERIFY_AND_COMMIT
|
||||||
if dry_run:
|
if dry_run:
|
||||||
print "P4 Runtime SetForwardingPipelineConfig:", request
|
print "P4Runtime SetForwardingPipelineConfig:", request
|
||||||
else:
|
else:
|
||||||
self.client_stub.SetForwardingPipelineConfig(request)
|
self.client_stub.SetForwardingPipelineConfig(request)
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ class SwitchConnection(object):
|
|||||||
update.type = p4runtime_pb2.Update.INSERT
|
update.type = p4runtime_pb2.Update.INSERT
|
||||||
update.entity.table_entry.CopyFrom(table_entry)
|
update.entity.table_entry.CopyFrom(table_entry)
|
||||||
if dry_run:
|
if dry_run:
|
||||||
print "P4 Runtime Write:", request
|
print "P4Runtime Write:", request
|
||||||
else:
|
else:
|
||||||
self.client_stub.Write(request)
|
self.client_stub.Write(request)
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ class SwitchConnection(object):
|
|||||||
else:
|
else:
|
||||||
table_entry.table_id = 0
|
table_entry.table_id = 0
|
||||||
if dry_run:
|
if dry_run:
|
||||||
print "P4 Runtime Read:", request
|
print "P4Runtime Read:", request
|
||||||
else:
|
else:
|
||||||
for response in self.client_stub.Read(request):
|
for response in self.client_stub.Read(request):
|
||||||
yield response
|
yield response
|
||||||
@ -121,7 +121,7 @@ class SwitchConnection(object):
|
|||||||
if index is not None:
|
if index is not None:
|
||||||
counter_entry.index.index = index
|
counter_entry.index.index = index
|
||||||
if dry_run:
|
if dry_run:
|
||||||
print "P4 Runtime Read:", request
|
print "P4Runtime Read:", request
|
||||||
else:
|
else:
|
||||||
for response in self.client_stub.Read(request):
|
for response in self.client_stub.Read(request):
|
||||||
yield response
|
yield response
|
||||||
|
@ -38,7 +38,7 @@ def configureP4Switch(**switch_args):
|
|||||||
switch's thrift server is using a unique port.
|
switch's thrift server is using a unique port.
|
||||||
"""
|
"""
|
||||||
if "sw_path" in switch_args and 'grpc' in switch_args['sw_path']:
|
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):
|
class ConfiguredP4RuntimeSwitch(P4RuntimeSwitch):
|
||||||
def __init__(self, *opts, **kwargs):
|
def __init__(self, *opts, **kwargs):
|
||||||
kwargs.update(switch_args)
|
kwargs.update(switch_args)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user