Featured image of post P4示例程序-4 组播与泛洪

P4示例程序-4 组播与泛洪

P4泛洪与组播的例程(泛洪借助组播实现)

背景描述

在P4实现的L2基本交换机的基础上,当L2交换机在表中无法查询到MAC地址或目的MAC地址为ff:ff:ff:ff:ff:ff时,泛洪至各交换机

本按钮使用两种方式进行实现:

  1. 首先搭建基本框架:泛洪至全部交换机(All-Port部分),即仅设置1个组播组
  2. 随后继续完善:泛洪至除源交换机外的各交换机(Other-Port部分)

拓扑图像

All-Port方式

拓扑配置JSON

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "p4_src": "p4src/l2_flooding_all_ports.p4",
  "cli": true,
  "pcap_dump": true,
  "enable_log": true,  
  "topology": {
    "assignment_strategy": "l2",
    "default": {
      "auto_arp_tables": false
    },
    "links": [["h1", "s1"], ["h2", "s1"], ["h3", "s1"], ["h4","s1"]],
    "hosts": {
      "h1": { },
      "h2": { },
      "h3": { },
      "h4": { }
    },
    "switches": {
      "s1": {
        "cli_input": "s1-commands-all-ports.txt"
      }
    }
  }
}

配置文件中设置auto_arp_tablesfalse,使得mininet不自动向主机下发ARP表

P4程序

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>

const bit<16> TYPE_IPV4 = 0x800;
const bit<16> TYPE_BROADCAST = 0x1234;

/*************************************************************************
*********************** H E A D E R S  ***********************************
*************************************************************************/
typedef bit<9>  egressSpec_t;
typedef bit<48> macAddr_t;
typedef bit<32> ip4Addr_t;

header ethernet_t {
    macAddr_t dstAddr;
    macAddr_t srcAddr;
    bit<16>   etherType;
}

struct metadata {
}

struct headers {
    ethernet_t ethernet;
}

/*************************************************************************
*********************** P A R S E R  ***********************************
*************************************************************************/
parser MyParser(packet_in packet,
                out headers hdr,
                inout metadata meta,
                inout standard_metadata_t standard_metadata) {
    state start {
        packet.extract(hdr.ethernet);
        transition accept;
    }
}

/*************************************************************************
************   C H E C K S U M    V E R I F I C A T I O N   *************
*************************************************************************/
control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
    apply { }
}

/*************************************************************************
**************  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) {
    action drop() {
        mark_to_drop(standard_metadata);
    }

    action forward(bit<9> egress_port) {
        standard_metadata.egress_spec = egress_port;
    }

    action broadcast() {
		// 设置转发的组播组ID为1
        standard_metadata.mcast_grp = 1;
    }

    table dmac {
        key = {
            hdr.ethernet.dstAddr: exact;
        }

        actions = {
            forward;
            broadcast;
            NoAction;
        }
        size = 256;
		// 默认动作应为broadcast 在表中无法查到MAC地址后 执行默认动作
		// 默认动作将在TXT配置文件中被更改
        default_action = NoAction;
    }

    apply {
        dmac.apply();
    }
}

/*************************************************************************
****************  E G R E S S   P R O C E S S I N G   *******************
*************************************************************************/
control MyEgress(inout headers hdr,
                 inout metadata meta,
                 inout standard_metadata_t standard_metadata) {
    apply { }
}

/*************************************************************************
*************   C H E C K S U M    C O M P U T A T I O N   **************
*************************************************************************/
control MyComputeChecksum(inout headers hdr, inout metadata meta) {
     apply { }
}

/*************************************************************************
***********************  D E P A R S E R  *******************************
*************************************************************************/
control MyDeparser(packet_out packet, in headers hdr) {
    apply {
        //parsed headers have to be added again into the packet.
        packet.emit(hdr.ethernet);
    }
}

/*************************************************************************
***********************  S W I T C H  *******************************
*************************************************************************/
//switch architecture
V1Switch(
    MyParser(),
    MyVerifyChecksum(),
    MyIngress(),
    MyEgress(),
    MyComputeChecksum(),
    MyDeparser()
) main;

运行测试

https://www.jianshu.com/p/c9e2303f33e4

s1-commands-all-ports.txt命令文件中,配置以下规则:

  1. 添加L2转发表:在dmac表中添加MAC地址与转发端口的映射,匹配成功后执行动作forward
  2. 设置dmac表格的默认动作为broadcast
  3. 使用mc_mgrp_create创建组播组ID=1
  4. mc_node_create:创建多播节点组0,组中包含2、3、4端口
  5. mc_node_associate:将多播节点组0与组播组1关联
  • mc_mgrp_createmc_node_createmc_node_associate为bmv2提供的RunTime CLI命令
1
2
3
4
5
6
7
8
9
table_add dmac forward 00:00:0a:00:00:01 => 1
table_add dmac forward 00:00:0a:00:00:02 => 2
table_add dmac forward 00:00:0a:00:00:03 => 3
table_add dmac forward 00:00:0a:00:00:04 => 4
table_set_default dmac broadcast

mc_mgrp_create 1
mc_node_create 0 1 2 3 4
mc_node_associate 1 0

ping前主机的ARP表:

ping后,主机学习到ARP表:

Other-Port

该方式中,当泛洪时,不向入端口进行转发

拓扑配置JSON

与All-Port方式一致

P4程序

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>

const bit<16> TYPE_IPV4 = 0x800;
const bit<16> TYPE_BROADCAST = 0x1234;

/*************************************************************************
*********************** H E A D E R S  ***********************************
*************************************************************************/
typedef bit<9>  egressSpec_t;
typedef bit<48> macAddr_t;
typedef bit<32> ip4Addr_t;

header ethernet_t {
    macAddr_t dstAddr;
    macAddr_t srcAddr;
    bit<16>   etherType;
}

struct metadata {
}

struct headers {
    ethernet_t   ethernet;
}

/*************************************************************************
*********************** P A R S E R  ***********************************
*************************************************************************/
parser MyParser(packet_in packet,
                out headers hdr,
                inout metadata meta,
                inout standard_metadata_t standard_metadata) {
    state start {
        packet.extract(hdr.ethernet);
        transition accept;
    }
}

/*************************************************************************
************   C H E C K S U M    V E R I F I C A T I O N   *************
*************************************************************************/
control MyVerifyChecksum(inout headers hdr, inout metadata meta) {
    apply { }
}

/*************************************************************************
**************  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) {
    action drop() {
        mark_to_drop(standard_metadata);
    }

    action forward(bit<9> egress_port) {
        standard_metadata.egress_spec = egress_port;
    }

    action broadcast() {
        // Empty action that was not necessary
		// we just call it when there is a table miss
    }

    table dmac {
        key = {
            hdr.ethernet.dstAddr: exact;
        }

        actions = {
            forward;
            broadcast;
            NoAction;
        }
        size = 256;
        default_action = NoAction;
    }

    action set_mcast_grp(bit<16> mcast_grp) {
        standard_metadata.mcast_grp = mcast_grp;
    }

    table select_mcast_grp {
        key = {
            standard_metadata.ingress_port : exact;
        }
        actions = {
            set_mcast_grp;
            NoAction;
        }
        size = 32;
        default_action =  NoAction;
    }

    apply {
		// TXT规则中将配置MAC地址与转发出端口的记录
		// 并将默认动作配置为broadcast
		// 因此当dmac.apply().action_run指示执行的动作是broadcast时
		// 表明查表失败 需要执行泛洪
        switch (dmac.apply().action_run) {
            broadcast: {
                select_mcast_grp.apply();
            }
        }

        /* Alternative Solution (even easier)
		// 该方式能实现同等功能
		// dmac.apply().hit将返回是否查表成功
		// 若查表失败 则执行泛洪
        if (dmac.apply().hit){
        }
        else {
            select_mcast_grp.apply();
        }

        End of Alternative solution
        */
    }
}

/*************************************************************************
****************  E G R E S S   P R O C E S S I N G   *******************
*************************************************************************/
control MyEgress(inout headers hdr,
                 inout metadata meta,
                 inout standard_metadata_t standard_metadata) {
    apply { }
}

/*************************************************************************
*************   C H E C K S U M    C O M P U T A T I O N   **************
*************************************************************************/
control MyComputeChecksum(inout headers hdr, inout metadata meta) {
    apply { }
}


/*************************************************************************
***********************  D E P A R S E R  *******************************
*************************************************************************/
control MyDeparser(packet_out packet, in headers hdr) {
    apply {
        //parsed headers have to be added again into the packet.
        packet.emit(hdr.ethernet);
    }
}

/*************************************************************************
***********************  S W I T C H  *******************************
*************************************************************************/
//switch architecture
V1Switch(
    MyParser(),
    MyVerifyChecksum(),
    MyIngress(),
    MyEgress(),
    MyComputeChecksum(),
    MyDeparser()
) main;

运行测试

s1-commands-other-ports.txt中:

  1. 添加L2转发表:在dmac表中添加MAC地址与转发端口的映射,匹配成功后执行动作forward
  2. 创建多播节点组0、1、2、3:例如多播节点组0包含端口2、3、4
  3. 创建组播组,并将多播节点组与组播组关联
  4. 添加映射关系:在select_mcast_grp中添加入端口号与组播组ID的映射,匹配成功后执行动作set_mcast_grp,例如从端口1进入的数据包通过组播组1发送出去
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
table_add dmac forward 00:00:0a:00:00:01 => 1
table_add dmac forward 00:00:0a:00:00:02 => 2
table_add dmac forward 00:00:0a:00:00:03 => 3
table_add dmac forward 00:00:0a:00:00:04 => 4
table_set_default dmac broadcast

#define broadcasting port groups
mc_node_create 0 2 3 4
mc_node_create 1 1 3 4
mc_node_create 2 1 2 4
mc_node_create 3 1 2 3

#associate node group with mcast group
mc_mgrp_create 1
mc_node_associate 1 0

mc_mgrp_create 2
mc_node_associate 2 1

mc_mgrp_create 3
mc_node_associate 3 2

mc_mgrp_create 4
mc_node_associate 4 3

#fill table selector
table_add select_mcast_grp set_mcast_grp 1 => 1
table_add select_mcast_grp set_mcast_grp 2 => 2
table_add select_mcast_grp set_mcast_grp 3 => 3
table_add select_mcast_grp set_mcast_grp 4 => 4
Licensed under CC BY-NC-SA 4.0
皖ICP备2025083746号-1
公安备案 陕公网安备61019002003315号



使用 Hugo 构建
主题 StackJimmy 设计