博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用p4实现ipv6转发实验
阅读量:6860 次
发布时间:2019-06-26

本文共 6840 字,大约阅读时间需要 22 分钟。

写在前面

只是作为一个入门p4的实验尝试,借用了一些即成的运行代码。


p4代码

/**p4_16,v1_model**/

1 #include
2 #include
3 4 const bit<16> TYPE_IPV6 = 0x08DD;//ipv6在以太网中的id 5 6 /*HEADERS*/ 7 8 typedef bit<9> egressSpec_t; 9 typedef bit<48> macAddr_t; 10 11 header ethernet_t{ 12 macAddr_t dstAddr; 13 macAddr_t srcAddr; 14 bit<16> etherType; 15 } 16 17 header ipv6_t{ 18 bit<4> version; 19 bit<8> trafficClass; 20 bit<20> flowLabel; 21 bit<16> payLoadLen; 22 bit<8> nextHdr; 23 bit<8> hopLimit; 24 bit<128> srcAddr; 25 bit<128> dstAddr; 26 } 27 28 struct metadata{ 29 } 30 31 struct headers{ 32 ethernet_t ethernet; 33 ipv6_t ipv6; 34 } 35 36 /*PARSER*/ 37 38 parser MyParser(packet_in packet,out headers hdr,inout metadata meta,inout standard_metadata_t standard_metadata){ 39 state start{ 40 transition parse_ethernet;//start开始先以底层eth解析 41 } 42 43 state parse_ethernet{ 44 packet.extract(hdr.ethernet); 45 transition select(hdr.ethernet.etherType){ 46 TYPE_IPV6:parse_ipv6;//转至ipv6解析 47 default:accept; 48 } 49 } 50 51 state parse_ipv6{ 52 packet.extract(hdr.ipv6); 53 transition accept; 54 } 55 } 56 57 /*CHECKSUM VERIFICATION*/ 58 59 control MyVerifyChecksum(inout headers hdr,inout metadata meta){ 60 apply{} 61 } 62 63 /*INGRESS PROCESSING*/ 64 65 control MyIngress(inout headers hdr,inout metadata meta,inout standard_metadata_t standard_metadata){ 66 action drop(){ 67 mark_to_drop();//将要丢弃的包标记为丢弃 68 } 69 70 action ipv6_forward(macAddr_t dstAddr,egressSpec_t port){ 71 standard_metadata.egress_spec = port; 72 hdr.ethernet.srcAddr = hdr.ethernet.dstAddr; 73 hdr.ethernet.dstAddr = dstAddr; 74 hdr.ipv6.hopLimit = hdr.ipv6.hopLimit - 1;//这个类似ipv4中ttl,为0时就超时 75 } 76 77 table ipv6_lpm{ 78 key = { 79 hdr.ipv6.dstAddr: lpm;//lpm是最长前缀匹配,exact完全匹配,ternary三元匹配 80 } 81 82 actions = { 83 ipv6_forward;//转发 84 drop;//丢弃 85 NoAction;//空动作 86 } 87 88 size = 1024;//流表项容量 89 90 default_action = drop();//table miss则丢弃 91 } 92 93 apply{ 94 if(hdr.ipv6.isValid()){ 95 ipv6_lpm.apply(); 96 } 97 } 98 } 99 100 /*EGRESS PROCESSING*/101 102 control MyEgress(inout headers hdr,inout metadata meta,inout standard_metadata_t standard_metadata){103 apply{}104 }105 106 /*CHECKSUM COMPUTATION*/107 108 control MyComputeChecksum(inout headers hdr,inout metadata meta){109 apply{}110 }111 112 /*DEPARSER*/113 114 control MyDeparser(packet_out packet,in headers hdr){115 apply{116 packet.emit(hdr.ethernet);117 packet.emit(hdr.ipv6);118 }119 }120 121 /*SWITCH*/122 123 V1Switch(124 MyParser(),125 MyVerifyChecksum(),126 MyIngress(),127 MyEgress(),128 MyComputeChecksum(),129 MyDeparser()130 )main;

 


实验拓扑

这里实验的拓扑用来最简单的一个交换机下挂两个主机,交换机是bmv2。其json文件书写如下: 交换机s1的流表项通过s1-commands.txt文件定义。

1 { 2     "program": "ipv6_forward.p4", 3     "language": "p4-16", 4     "targets": { 5       "multiswitch": { 6           "auto-control-plane": true, 7           "cli": true, 8           "pcap_dump": true, 9           "bmv2_log": true,10           "links": [["h1", "s1"], ["h2", "s1"]],11           "hosts": {12             "h1": {13             },14             "h2": {15             }16           },17           "switches": {18               "s1": {19                   "entries": "s1-commands.txt"20               }21         }22     }23     }24 }

 

 

在s1-commans.txt文件中做如下定义:

1 table_set_default ipv6_lpm drop2 table_add ipv6_lpm ipv6_forward fe80::5678/128 => 00:04:00:00:00:02 23 table_add ipv6_lpm ipv6_forward fe80::1234/128 => 00:04:00:00:00:01 1

将其流表项画出来如下:


收发包脚本代码

鉴于对python socket发包代码不是那么了解,所以套用了一部分模板做了修改。

send.py

1 import argparse 2 import sys 3 import socket 4 import random 5 import struct 6  7 from scapy.all import sendp, send, get_if_list, get_if_hwaddr 8 from scapy.all import Packet 9 from scapy.all import Ether, IPv6, UDP10 11 def get_if():12     ifs=get_if_list()13     iface=None14     for i in get_if_list():15         if "eth0" in i:16             iface=i17             break;18     if not iface:19         print "Cannot find eth0 interface"20         exit(1)21     return iface22 23 def main():24 25     if len(sys.argv)<3:26         print 'pass 3 arguments: 
"
"'27 exit(1)28 saddr = sys.argv[1]29 addr = sys.argv[2]30 iface = get_if()31 32 print "sending on interface %s to %s" % (iface, str(addr))33 pkt = Ether(src=get_if_hwaddr(iface), dst='ff:ff:ff:ff:ff:ff') / IPv6(src=saddr,dst=addr) / UDP(dport=4321, sport=1234) / sys.argv[3]34 pkt.show2()35 sendp(pkt, iface=iface, verbose=False)36 37 38 if __name__ == '__main__':39 main()

 

 

receive.py

1 import sys 2 import struct 3 import os 4  5 from scapy.all import sniff, sendp, hexdump, get_if_list, get_if_hwaddr 6 from scapy.all import Packet, IPOption 7 from scapy.all import ShortField, IntField, LongField, BitField, FieldListField, FieldLenField 8 from scapy.all import IPv6, TCP, UDP, Raw 9 from scapy.layers.inet import _IPOption_HDR10 11 def get_if():12     ifs=get_if_list()13     iface=None14     for i in get_if_list():15         if "eth0" in i:16             iface=i17             break;18     if not iface:19         print "Cannot find eth0 interface"20         exit(1)21     return iface22 23 class IPOption_MRI(IPOption):24     name = "MRI"25     option = 3126     fields_desc = [ _IPOption_HDR,27                     FieldLenField("length", None, fmt="B",28                                   length_of="swids",29                                   adjust=lambda pkt,l:l+4),30                     ShortField("count", 0),31                     FieldListField("swids",32                                    [],33                                    IntField("", 0),34                                    length_from=lambda pkt:pkt.count*4) ]35 def handle_pkt(pkt):36     print "got a packet"37     pkt.show2()38     #hexdump(pkt)39     sys.stdout.flush()40 41 42 def main():43     ifaces = filter(lambda i: 'eth' in i, os.listdir('/sys/class/net/'))44     iface = ifaces[0]45     print "sniffing on %s" % iface46     sys.stdout.flush()47     sniff(filter="udp and port 4321",iface = iface,48           prn = lambda x: handle_pkt(x))49 50 if __name__ == '__main__':51     main()

 

 


测试

1 ./run.sh2 //在mininet cli中3 xterm h1 h24 //在h2中5 ./receive.py6 //在h1中7 ./send.py fe80::1234 fe80::5678 "Hello p4!"

 

结果如下:


牢骚

第一次尝试构建p4相关的实验,了解了一部分p4的语法,以及一些的工作原理,也发掘出一部分并未了解的知识内容待后续去琢磨学习。过程有很多不完美,结果也有很多不完美,虽然现在也不满足,但是寒假也快结束了。

转载于:https://www.cnblogs.com/pullself/p/10418743.html

你可能感兴趣的文章