写在前面

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


p4代码

/**p4_16,v1_model**/

  1. #include<core.p4>
  2. #include<v1model.p4>
  3.  
  4. const bit<> TYPE_IPV6 = 0x08DD;//ipv6在以太网中的id
  5.  
  6. /*HEADERS*/
  7.  
  8. typedef bit<> egressSpec_t;
  9. typedef bit<> macAddr_t;
  10.  
  11. header ethernet_t{
  12. macAddr_t dstAddr;
  13. macAddr_t srcAddr;
  14. bit<> etherType;
  15. }
  16.  
  17. header ipv6_t{
  18. bit<> version;
  19. bit<> trafficClass;
  20. bit<> flowLabel;
  21. bit<> payLoadLen;
  22. bit<> nextHdr;
  23. bit<> hopLimit;
  24. bit<> srcAddr;
  25. bit<> 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 - ;//这个类似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 = ;//流表项容量
  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 drop
  2. table_add ipv6_lpm ipv6_forward fe80::5678/128 => 00:04:00:00:00:02 2
  3. 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, UDP
  10.  
  11. def get_if():
  12. ifs=get_if_list()
  13. iface=None
  14. for i in get_if_list():
  15. if "eth0" in i:
  16. iface=i
  17. break;
  18. if not iface:
  19. print "Cannot find eth0 interface"
  20. exit(1)
  21. return iface
  22.  
  23. def main():
  24.  
  25. if len(sys.argv)<3:
  26. print 'pass 3 arguments:<source> <destination> "<message>"'
  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. if __name__ == '__main__':
  38. 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_HDR
  10.  
  11. def get_if():
  12. ifs=get_if_list()
  13. iface=None
  14. for i in get_if_list():
  15. if "eth0" in i:
  16. iface=i
  17. break;
  18. if not iface:
  19. print "Cannot find eth0 interface"
  20. exit(1)
  21. return iface
  22.  
  23. class IPOption_MRI(IPOption):
  24. name = "MRI"
  25. option = 31
  26. 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. def main():
  42. ifaces = filter(lambda i: 'eth' in i, os.listdir('/sys/class/net/'))
  43. iface = ifaces[0]
  44. print "sniffing on %s" % iface
  45. sys.stdout.flush()
  46. sniff(filter="udp and port 4321",iface = iface,
  47. prn = lambda x: handle_pkt(x))
  48.  
  49. if __name__ == '__main__':
  50. main()

测试

  1. ./run.sh
  2. //在mininet cli中
  3. xterm h1 h2
  4. //在h2中
  5. ./receive.py
  6. //在h1中
  7. ./send.py fe80::1234 fe80::5678 "Hello p4!"

结果如下:


牢骚

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

利用p4实现ipv6转发实验的更多相关文章

  1. SSH的本地、远程、动态端口转发实验笔记

    SSH端口转发 SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据.但是,SSH 还能够将其他 TCP 端口的网络数据通过 SSH 链接来转发,并且自动提供了相应的加密及解密服务.这一 ...

  2. 哈工大 计算机网络 实验三 IPv4 分组收发实验&IPv4 分组转发实验

    计算机网络实验代码与文件可见github:计算机网络实验整理 实验名称 IPv4 分组收发实验&IPv4 分组转发实验 实验目的: (注:实验报告模板中的各项内容仅供参考,可依照实际实验情况进 ...

  3. 老毛子 Padavan 路由器固件开启教育网 IPv6 并实现IPv6转发

    老毛子 Padavan 路由器固件开启教育网 IPv6 并实现IPv6转发 文章目录[隐藏] 一.开启opt环境 二.开启 WAN 端 IPv6 三.安装并运行 6relayd 四.开机自动安装并配置 ...

  4. 利用IIS应用请求转发ARR实现IIS和tomcat整合共用80端口

    现在网上流传的实现iis和tomcat共享80端口的方法是基于isapi_redirect插件实现的, 我的实现方法不同, 原理相似,具有更好的优点. 先说下基于isapi_redirect缺点,ja ...

  5. 利用php设置url转发 - 解决空间不提供子目录绑定功能的问题

    由于很多新手都是使用的虚拟空间都是最便宜的那种,这空间一般不支持子目录绑定.但是很多朋友又想设置几个不同的二级域名访问不同的网站程序.于是大家找到了域名url转发,但是由于国家政策的原因,许多服务商暂 ...

  6. 利用iptables做端口转发

    需求背景: A与C不在同一网段无法直接访问,而A和B,C和B可以互通.现需要A借助B访问C的3306端口. 解决方案: 利用iptables配置规则,实现端口转发. 具体操作: 在B上开启端口转发功能 ...

  7. 利用binlogserver恢复单表实验【转】

    使用场景 每次开启binlogserver 指定了mysql-bin.0000XX 后都会从该点从头进行传输一次 创建binlogserver [root@mysql-zst3 binlogserve ...

  8. 关于利用GPG加解密的实验

    GnuPG(GNU Privacy Guard,简称:GPG)为一款免费开源的使用非对称密钥加密(asymmetric cryptography)之软件,最初由Werner Koch开发,该软件使用非 ...

  9. 利用iptables做网络转发

    常见的网络拓扑图结构如下: 但是内网服务器偶尔有上网需求,比如yum工具,wget文件.而我们又不能让重要业务直接暴露在公网上. 好用的安全策略有:三层交换机.路由器做nat映射,防火墙做安全策略. ...

随机推荐

  1. ionic ios 打包 真机测试常见问题

    1.ionic 项目在windows下正常打包安卓包时  迁移到mac下打包ios时  不需要复制平台目录platforms即可  不用再mac下去安装各种插件信息 2.ionic 下不能访问api信 ...

  2. PHP程序员学Objective-C之后的变化

    趣味坎谈,不一定100%准确,以自己的实际情况为准; 如题,我2008年开始学PHP,PHP是我学的第二门编程语言,一直用到现在,2010年初开始做iOS开发,学习了Objective-C,学这2门语 ...

  3. hello,Python

    Python无疑是近年来程序语言届最闪亮的明星.2018年Python被TIOBE授予年度编程语言称号,在一月的排行榜中也雄踞第三位,打破了Java C C++长期以来所保持的三强局面 对比笔者以前学 ...

  4. android studio 调试技巧(简直太好用)

    android studio 调试技巧(简直太好用) 说到android studio的调试,很多人可能会说,这有什么可讲的不就是一个断点调试么,刚开始我也是这么认为的,直到我了解之后,才发现,调试原 ...

  5. scala(9) Monad

    一个单子(Monad)说白了不过就是自函子范畴上的一个幺半群而已.这句话涉及到了几个概念:单子(Monad),自函子(Endo-Functor),幺半群(Monoid),范畴(category). 范 ...

  6. 脱离matlab运行可执行程序的步骤

    MCR是由matlab的运行环境,占用不到600M的对于用不同matlab版本生成的exe文件,MCR版本也会有不同,因此,在程序打包时,最好将相应版本的MCR一起打包.MCR环境的设置文件存放目录如 ...

  7. css position:absolute align center bottom

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. Linux入门第二天——基本命令入门(中)

    一.文件搜索命令 1.文件搜索命令:locate 速度很快(具体见Linux工具网址的对比),注意无法找到新建的文件(原理暂不展开) locate命令其实是“find -name”的另一种写法,但是要 ...

  9. ruby学习笔记(3)- 新手入门

    这里是一个Ruby开发的快速参考指南: Ruby是什么 ? Ruby是一种纯粹的面向对象编程语言.它由日本松本幸创建于1993年. Ruby是一种通用的解释编程语言如Perl和Python. IRb是 ...

  10. 【原创】Odoo开发文档学习之:ORM API接口(ORM API)(边Google翻译边学习)

    官方ORM API开发文档:https://www.odoo.com/documentation/10.0/reference/orm.html Recordsets(记录集) New in vers ...