#!/usr/bin/env python2 import argparse import grpc import os import sys from time import sleep
# Import P4Runtime lib from parent utils dir # Probably there's a better way of doing this. sys.path.append( os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../utils/')) import p4runtime_lib.bmv2 from p4runtime_lib.switch import ShutdownAllSwitchConnections import p4runtime_lib.helper
SWITCH_TO_HOST_PORT = 1 SWITCH_TO_SWITCH_PORT = 2
defwriteTunnelRules(p4info_helper, ingress_sw, egress_sw, tunnel_id, dst_eth_addr, dst_ip_addr): """ Installs three rules: 1) An tunnel ingress rule on the ingress switch in the ipv4_lpm table that encapsulates traffic into a tunnel with the specified ID ipv4_lpm表的入接口开关上的隧道入接口规则,该规则用指定的ID将流量封装到一个隧道中 2) A transit rule on the ingress switch that forwards traffic based on the specified ID 入口交换机上的一种传输规则,根据指定的ID转发流量 3) An tunnel egress rule on the egress switch that decapsulates traffic with the specified ID and sends it to the host 出口交换机上的一条隧道出口规则,将指定ID的流量解封装后发送给主机 :param p4info_helper: the P4Info helper :param ingress_sw: the ingress switch connection :param egress_sw: the egress switch connection :param tunnel_id: the specified tunnel ID :param dst_eth_addr: the destination IP to match in the ingress rule :param dst_ip_addr: the destination Ethernet address to write in the egress rule """ # 1) Tunnel Ingress Rule table_entry = p4info_helper.buildTableEntry( table_name="MyIngress.ipv4_lpm", match_fields={ "hdr.ipv4.dstAddr": (dst_ip_addr, 32) }, action_name="MyIngress.myTunnel_ingress", action_params={ "dst_id": tunnel_id, }) ingress_sw.WriteTableEntry(table_entry) print"Installed ingress tunnel rule on %s" % ingress_sw.name
# 2) Tunnel Transit Rule # The rule will need to be added to the myTunnel_exact table and match on the tunnel ID (hdr.myTunnel.dst_id). Traffic will need to be forwarded using the myTunnel_forward action on the port connected to the next switch.这条规则是添加到myTunnel_exact table上面的,match的部分是tunnel ID (hdr.myTunnel.dst_id)。流量将会使用myTunnel_forward action转发到连接下一个交换机的端口,这里要观察下面的拓扑图会发现连接交换机(h1,h2)的都是二号端口,文件里面用SWITCH_TO_SWITCH_PORT表示了2号端口 # # For our simple topology, switch 1 and switch 2 are connected using a link attached to port 2 on both switches. We have defined a variable at the top of the file, SWITCH_TO_SWITCH_PORT, that you can use as the output port for this action. # # We will only need a transit rule on the ingress switch because we are using a simple topology. In general, you'll need on transit rule for each switch in the path (except the last switch, which has the egress rule), and you will need to select the port dynamically for each switch based on your topology.
# TODO build the transit rule # TODO install the transit rule on the ingress switch #print "TODO Install transit tunnel rule" table_entry=p4info_helper.buildTableEntry( table_name="MyIngress.myTunnel_exact", match_fields={ "hdr.myTunnel.dst_id":tunnel_id }, action_name="MyIngress.myTunnel_forward", action_params={ "port":SWITCH_TO_SWITCH_PORT }) ingress_sw.WriteTableEntry(table_entry) print"Installed transit tunnel rule on %s" % ingress_sw.name # 3) Tunnel Egress Rule # For our simple topology, the host will always be located on the SWITCH_TO_HOST_PORT (port 1). # In general, you will need to keep track of which port the host is connected to. table_entry = p4info_helper.buildTableEntry( table_name="MyIngress.myTunnel_exact", match_fields={ "hdr.myTunnel.dst_id": tunnel_id }, action_name="MyIngress.myTunnel_egress", action_params={ "dstAddr": dst_eth_addr, "port": SWITCH_TO_HOST_PORT }) egress_sw.WriteTableEntry(table_entry) print"Installed egress tunnel rule on %s" % egress_sw.name #### 下面的函数省略不表
/************************************************************************* ************** I N G R E S S P R O C E S S I N G ******************* *************************************************************************/
control MyIngress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata){