源码解读ODL的MAC地址学习(一)

1 简介

我们知道同一子网中主机之间互相传送信息需要用到MAC地址,而我们第一次发送信息的时候只有IP地址而没有MAC地址,所以我们就要进行MAC地址自学习。

交换机中的MAC地址自学习是指在交换机中有一个MAC地址与交换机每个接口的对应表,每当有数据包经过交换机转发的时候,如果它的表中没有这个MAC地址的对应关系就会往所有端口转发数据包,当目标机从某个端口返回信息的时候它就知道了这个MAC地址对应的哪个端口,于是会把这个对应关系加入表中,这个过程就是交换机的MAC地址自学习。

2 ODL中MAC地址原理

前文已经介绍了MAC地址自学的一般过程,在ODL中,我们监控ARP数据包来学习MAC地址,将ARP数据包通过Packet-In消息发给OpenFlow控制器,那么就可以在不过度加重OpenFlow控制器负载的情况下,实现MAC地址学习。

ODL MAC地址学习的源码主要集中在l2switch和OpenFlowPlugin模块:

红框标注的内容就是l2switch项目中和MAC地址学习有关的,未标注的部分是链路和节点发现;OpenFlow项目中涉及到MAC地址学习的不多,只有一个定义Packet-In和Packet-Out的YANG文件:packet-processing.yang。下面我们会从ARP处理流程出发,具体分析源码,由于篇幅有限,源码中不是很重要的部分没有贴出来,要看完整的源码请下面网址下载:
https://github.com/opendaylight/l2switch/tree/stable/beryllium
https://github.com/opendaylight/openflowplugin/tree/stable/beryllium
同时重要代码的具体分析直接在注释里面。

2.1 ARP处理流程

我们设想一种场景,如图所示:

PC A准备向IPv4地址为10.0.0.2的目标地址发送数据包。此时,假设PC A的ARP表中不存在10.0.0.2这一表项,那么PC A不知道10.0.0.2这一IPv4地址对应的以太网地址,所以准备使用ARP解决该问题。

PC A通过L2广播发送ARP请求,PC B接收该请求后发送ARP响应。PC A接收到ARP响应后将PC B的以太网地址存储到ARP表中。这样,PC A就可以向10.0.0.2这一IPv4地址发送数据包。

以上就是ARP的处理流程,下面我们对流程中的细节进行相应的阐述。

2.2 ARP请求(Packet-In)

首先,PC A发送ARP请求,由OpenFlow交换机接收到该请求,OpenFlow交换机接收到PC A发来的ARP请求之后,检索流表,此时的流表是通过Proactive模式加载的流表,其中的流表项的匹配字段是入端口,行动是上报控制器,这个流表项的具体实现代码存在于l2switch项目中arphandler目录下的ProactiveFloodFlowWriter.java:

设置OutPut的action为controller,即上报给控制器。

流表项匹配成功之后,OpenFlow交换机执行通过Packet-In消息向OpenFlow控制器转发ARP请求帧的行动。此时ODL控制器就要做两个处理,一是接受Packet-In消息,而是对Packet-In消息进行解码。

首先看一下Packet-In消息的接收。Packet-In消息的定义YANG文件存在于OpenFlowPlugin项目中的packet-processing.yang:

将收到的Packet-In的数据包定义成notification,那么编译之后就会出现PacketProcessingListener.java接口类,为了订阅这个消息来对收到的数据包进行处理,在代码中就要实现这个接口类(implements PacketProcessingListener)。

下面我们来分析对Packet-In数据包的解码,代码的实现逻辑是:先将packet-received数据包解码成ethernet-packet数据包,再将ethernet-packet数据包解码成相应的arp-packet、ipv4-packet和ipv6-packet数据包。具体的实现代码存在于l2switch项目中的packethandler这个目录下。首先我们分析YANG文件:

首先是packet.yang:

这个YANG文件定义了基本数据包,便于具体数据包的YANG文件扩展,该YANG文件中比较重要的就是这个grouping,其他YANG文件扩展的就是packet-chain。同时这个YANG文件还有一点需要注意:这个YANG文件的文件名是packet.yang,但是它的module名是base-packet,所以import的时候用的是base-packet,而不是packet。

下面我们分析ethernet-packet.yang,至于arp-packet.yang,ipv4-packet.yang和ipv6-packet.yang文件和这个文件差不多,就不多做分析了。

该YANG文件中最重要的就是这个notification,从上述代码中可以发现它扩展了packet.yang中packet-chain中的packet,添加了一个情况:ethernet-packet。

分析完了YANG文件,下面我们来看下具体的解码java代码,前面提到过,解码分为两个步骤,先将packet-received数据包解码成ethernet-packet数据包,再将ethernet-packet数据包解码成相应的arp-packet、ipv4-packet和ipv6-packet数据包。下面我们分析三个java文件:
AbstarctPacketDecoder.java:

这个文件定义了一个抽象java类,用于实现注册监听器、将ConsumedPacketNotification消息解码成ProducedPacketNotification类型的消息,并把这个消息发出去。这个java类中并没有实现具体的解码过程,只定义了一个抽象的decode()方法,便于其他的java类覆写。
EthernetDecoder.java:

这个类监听PacketReceived消息,当收到数据包时,将此时的数据包作为RawPacket并解码成EthernetPacket数据包,最后将EthernetPacketReceived消息发出去,这里面的PacketReceived数据包就是Packet-In数据包,这个的定义YANG存在与OpenFlowPlugin项目中,我们在前面已经分析过了,这里就不多做赘述。

ArpDecoder.java

由于ARP报文存在与以太网的报文的帧头部,所以为了得到ARP报文,就要订阅EthernetPacketReceived消息,所以ArpDecoder这个类实现了EthernetPacketListener接口。ARP报文的格式如下图所示:

具体的解码过程就是根据的ARP报文格式,具体的代码解释在注释中,这里就不多做赘述了。

EthernetPacket数据包也可以解码成Ipv4Packet和Ipv6Pcket数据包,相应的实现代码在Ipv4Decoder.java和Ipv6Decoder.java中,代码逻辑类似,这里因为篇幅限制就不多做解释,感兴趣的可以私信我。

以上就是收到ARP请求,并将相应的数据包解码成ArpPacket、Ipv4Packet和Ipv6Pcket数据包。

2.3 ARP请求(Packet-Out)

为了将来自PC A的ARP请求广播至OpenFlow网络内,ODL控制器将Packet-Out消息发送至OpenFlow交换机,接受到Packet-Out消息的OpenFlow交换机,将ARP请求广播至端口2和端口3。具体的实现代码在l2switch项目中的arphandler目录下。

首先我们来分析ArpPacketHandler.java,这个java类是这个部分的核心。

ArpPacketHandler.java实现了对ARP数据包的监听,同时对数据包进行相应的处理,得到相应的原始数据包、以太网数据包和ARP数据包,调用packetDispatcher类中的dispatchPacket()函数,传入相应的参数,这个函数主要的作用是将数据包Packet-Out出去。下面我们就来分析下packetDispatcher.java。

这个类主要的实现功能是将数据包广播或者单播出去,分析代码可以发现,对于已知目的端口数据包直接从目的端口(destNodeConnector)Packet-Out出去,不知道目的端口的就向所有的SwitchNodeConnectors端口广播出去,那么我们现在就需要得到SwitchNodeConnectors,这部分的代码在InventoryReader中。

这个类主要实现了两个功能,一是得到相应的controllerSwitchConnectors和switchNodeConnectors用于Packet-Out数据包的单播和广播,controllerSwitchConnectors是端口名有local的端口,实际中,switch-to-switch ports和switch-to-controller ports是含有local的,而connected-to-host ports是不含local的;二是根据host的mac地址得到连接的端口。

根据以上的分析,由于PC A不知道IPv4地址为10.0.0.2的MAC地址,所以要将ARP请求广播。

3 总结

以上就是ARP请求的具体分析,ARP请求完了之后会有ARP响应,ARP相应结束ODL控制器也会下发相应的流表,由于篇幅限制,这部分的源码分析在我的下一篇文章中(源码解读ODL MAC学习(二))。

作者简介:吴琪 2015.09-至今 于北京邮电大学信息光子学与光通信国家重点实验室攻读硕士研究生

鸣谢:本文是作者实习期间所做总结,感谢中国电信北京研究院SDN技术研发中心对本文的指导和支持!


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/17581.html
分享到:
相关文章
条评论

登录后才可以评论

吴琪 发表于16-08-10
3