OpenFlow协议抓包实验

1 操作步骤

本实验采用opendaylight控制器和mininet,使用mininet连接opendaylight。连接后pingall测试连接是否成功,测试完连通性后进行抓包实验。

打开wireshark抓包:

2 OpenFlow1.0协议解析

控制器通过Openflow管理、控制交换机,分析wireshark抓到的OpenFlow包就可以大体推测控制器与交换机通信的流程。虽然没有进行任何操作,但是一旦交换机连接控制器,wireshark就能捕捉到很多OpenFlow包。依次是hello消息、feature消息,stats消息,以及packet_in和packet_out。

2.1 Hello

控制器与交换机建立连接时由其中某一方发起Hello消息,双方协调协议版本号。Hello消息只有of包头,没有主体部分。而of头部结果如下:

Hello消息如下:

  1. Version:OpenFlow版本,低位为版本号,如上所示。
  2. Type:OpenFlow消息类型,主要包括:

注:

  1. Length:消息总长度,包含头部。
  2. Xid:事件ID,同一件事件的ID号一致。如feature_request和对应的feature_reply就使用同一个Transaction id,但是两个hello消息的Transaction id并不相同,不过据实验结果看两个id一般是两个相邻的数字。并且packet_in的transaction id都为0。

    2.2 Feature消息

    TLS会话一建立,控制器就会向交换机发送一个ofpt_feature_request消息,该消息只有of包头,如下所示。交换机会回复一条ofpt_feature_reply消息。
    ofpt_feature_request如图:(有时候会发现一个数据包中有多个request,并且后面会有一一对应的reply包。)

    ofpt_feature_reply如图:

    ofpt_feature_reply消息结构如下:

注:

  1. datapath_id:数据通道独一无二的标识符,低48位是一个MAC地址,而高16位是自定义的。例如,用高16位代表VLAN ID区别一个物理交换机中的多个虚拟交换机。
  2. n_buffers:一次最多缓存的数据包数量。
  3. n_tables:表示交换机支持的流表数量。而每个流表可以设置不同的通配符和不同数量的流表项。控制器和交换机第一次通信的时候,控制器会从feature_reply消息中找出交换机支持多少流表,如果控制器还想了解大小、类型和流表查询的顺序,就发送一个ofpst_table stats请求,交换机必须按照数据包遍历流表的顺序把这些流表回复给控制器,并且精确匹配流表排在通配流表前。
  4. capabilities:所支持的功能,该字段使用以下flags:

注:

  1. actions:该bitmask表示交换机所支持的actions,“required”action必须支持,vendor action不应该通过该bitmask显示,actions根据ofp_action_type的值决定需要左移几位。
  2. ports[0]:以数组的形式罗列出该系统中支持OpenFlow的物理端口。数据长度可以根据OpenFlow头部中的length推测出来。

    2.3 Packet_in消息

    当交换机碰到新数据包不知道如何处理,或者action要求发送给控制器,那么交换机就会用packet_in消息发送给控制器。一般将数据包缓存在交换机中,将有效的数据包信息(默认的128字节,如果原因是 “send to controller” action,那么长度由action_out的max_len决定;如果是原因table miss,那么长度由set_config消息中的miss_send_len决定。)和缓存id发送给控制器,不过,如果交换机不支持缓存或者内存用光了,那么就把整个数据包放在数据部分发给控制器,并且缓存id为-1。

Packet_in消息如下:

Packet_in消息结构如下:

  1. buffer_id:数据通道分配的缓存id,标志数据包存在交换机中的位置,如果没有缓存在交换机中则buffer_id则为-1。
  2. total_len:整个数据帧的长度。
  3. in_port:接收数据帧的端口。
  4. reason:将数据包发送给控制器的原因,一般有俩原因,一是没有匹配到流表项,二是动作要求发给控制器。

2.4 Packet_out消息

当控制器希望交换机发送某个数据包,就使用packet_out消息。Packet_out消息如下所示:

Packet_out消息结构如下:

buffer_id:与packet_in中给的一样,如果为-1就表明数据包附在数据数组中。

2.5 Configuration消息

控制器可以发送OFPT_SET_CONFIG / OFPT_GET_CONFIG_REQUEST消息设置/查询交换机配置参数,交换机只需响应OFPT_GET_CONFIG_REQUEST消息即可。
OFPT_SET_CONFIG消息如下所示:

OFPT_GET_CONFIG_REQUEST消息没有消息主体,OFPT_SET_CONFIG 、OFPT_GET_CONFIG_reply的消息结构如下所示:

  1. Flags:配置类型flags,主要包括:

注:

  1. miss_send_len:决定发送给控制器的数据包长度,如果该字段为0,则交换机发送一个大小为0的packet_in消息。

    2.6 Stats消息

    交换机和控制器连接后,控制器会不断发送stats消息询问交换机的状态,就好像两个打电话的人,一方不断询问“你在吗?”另一方不断回答“在呀!”抓到的stats消息如下所示:

    ofp_stats_request和ofp_stats_reply消息结构相同,都使用以下结构:

注:

  1. Type:该字段决定传递的信息的类型并且怎样解释body部分。主要包括:

注:

  1. Flags:ofp_stats_request的flag字段目前还没有定义,而reply消息的flag字段只有一个值0x0001,该值表示后面是否还有更多的reply。

    2.7 Flow_mod

    控制器与交换机建立连接后,控制器会自发给交换机发送一组flow_mod消息,抓到的消息如下:

flow_mod消息结构:

  1. Cookie: 控制器设置的不透明数据。当command为OFPFC_MODIFY或OFPFC_MODIFY_STRICT时,匹配了的流表项需要适当的更新cookie字段。
  2. Command可能会是

注:

  1. idle_timeout和hard_timeout控制流表项的生命周期。当idle_timeout为x(x不为0)并且hard_timeout为0时,流表项在x秒收不到数据包后就到期。当idle_timeout为0并且hard_timeout为x时,x秒后无论收不收得到数据包流表项都到期。当idle_timeout为x(x不为0)并且hard_timeout为y(y不为0)时,x秒收不到数据包或者y秒后,哪个期限先到就按哪个算。当idle_timeout和hard_timeout都为0时,表明这个流表项是永恒的,除非用OFPFC_DELETE删除,否则不会到期。
  2. priority:priority只和含通配字段的流表项有关。Priority值越大,表明流表优先级越高。交换机必须将优先级最高的通配流表项放在编号最低的通配流表中。无论流表是什么配置,交换机需要确保精确流表项排在通配流表项之前。
  3. buffer_id:标志由packet_in消息发送的数据包存储的地方。
  4. out_port:delete和delete_strict消息利用该字段确定作用域,而add、modify、modify_strict消息会自动忽略该字段。如果out_port为ofpp_none则表明禁用output端口过滤功能,否则就相当于添加了一个额外的匹配限制条件。连0也是有效端口id,表示约束条件是必须有关于该端口的output动作。而ofp_match和优先级等条件依旧生效,该字段只是添加了一个额外的约束。
  5. flags:flags主要包括:

注:

(1)、设置OFPFF_SEND_FLOW_REM标识表示当流表项到期时交换机发送一条flow removed消息,一般默认情况下交换机是不会为新添加的流表项发送flow removed消息的。

(2)、OFPFF_CHECK_OVERLAP生效表明交换机必须检查是否有优先级冲突的流表项,如果冲突,则flow mod无效并且回复错误提醒。

(3、)OFPFF_EMERG为1则代表该流表项是紧急流表项,当交换机与控制器断开连接时就利用该表项转发数据包。