基础要求
代码
#!/usr/bin/env python
from mininet.net import Mininet
from mininet.node import Controller, RemoteController, OVSController
from mininet.node import CPULimitedHost, Host, Node
from mininet.node import OVSKernelSwitch, UserSwitch
from mininet.node import IVSSwitch
from mininet.cli import CLI
from mininet.log import setLogLevel, info
from mininet.link import TCLink, Intf
from subprocess import call
def myNetwork():
net = Mininet( topo=None,
build=False,
ipBase='192.168.0.0/24')
info( '*** Adding controller\n' )
c0=net.addController(name='c0',
controller=Controller,
protocol='tcp',
port=6633)
info( '*** Add switches\n')
s2 = net.addSwitch('s2', cls=OVSKernelSwitch)
s1 = net.addSwitch('s1', cls=OVSKernelSwitch)
info( '*** Add hosts\n')
h2 = net.addHost('h2', cls=Host, ip='192.168.0.102/24', defaultRoute=None)
h4 = net.addHost('h4', cls=Host, ip='192.168.0.104/24', defaultRoute=None)
h3 = net.addHost('h3', cls=Host, ip='192.168.0.103/24', defaultRoute=None)
h1 = net.addHost('h1', cls=Host, ip='192.168.0.101/24', defaultRoute=None)
info( '*** Add links\n')
net.addLink(h1, s1)
net.addLink(s1, h3)
net.addLink(s1, s2)
net.addLink(s2, h2)
net.addLink(s2, h4)
info( '*** Starting network\n')
net.build()
info( '*** Starting controllers\n')
for controller in net.controllers:
controller.start()
info( '*** Starting switches\n')
net.get('s2').start([c0])
net.get('s1').start([c0])
info( '*** Post configure switches and hosts\n')
CLI(net)
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
myNetwork()
抓包结果截图
OFPT_HELLO
- hello 是使用来协商控制器和交换机之间openflow协议的版本号的消息。当控制器和交换机都支持openflow1.0时,使用1.0版本进行交流;
从控制器6633端口到交换机57646端口,使用OpenFlow1.0协议
从交换机57646端口到控制器6633端口,使用OpenFlow1.5协议
OFPT_HELLO后双方协定使用OpenFlow1.0协议
OFPT_FEATURES_REQUEST
- feature_request消息是控制器用来查询交换机特性的消息,如交换机ID,缓冲区数量,端口及端口属性等。该消息只有头部,没有消息体。
从控制器6633端口到交换机57646端口,请求特征信息。
OFPT_SET_CONFIG
- set_config消息是控制器对交换机进行配置的消息。控制器可以配置交换机的MTU,报文分片处理等能力。
从控制器6633端口到交换机57646端口,按照控制器要求配置交换机
OFPT_FEATURES_REPLY
- 交换机收到feature_request消息之后会回复feature_reply消息来报告自己的特性。具体来说,会有交换机自身支持的流表数量,最多能缓存的数据包数量,端口特性等。交换机报告自身的特性之后,控制器能够根据这些特性下发指令。
交换机57646端口到控制器6633端口,回复特征信息。
OFPT_PACKET_IN
- 该消息有两种发送情况:
1.当交换机查找流表,发现没有匹配条目,不知道如何转发的报文时,使用packet_in消息将无法处理的报文封装起来发送给控制器,交给控制器去判断处理。并且交换机会将该数据包缓存。
2.交换机中有匹配条目但是对应的action是OUTPUT=CONTROLLER,该报文的匹配动作就是发送给控制器,这时交换机也会将该报文用packet_in消息封装,发送给控制器。
交换机将包上报给控制器请求处理
OFPT_PACKET_OUT
控制器6633端口向交换机57646端口,告知交换机应输出包到哪一端口
OFPT_FLOW_MOD
- flow_mod消息是OpenFlow协议的核心消息之一。flow_mod消息的作用是下发流表项。通过Flow-Mod消息可以对流表进行添加、删除、变更设置等操作。
控制器通过6633端口向交换机57646端口下发流表项,指导数据的转发处理
进阶要求
OpenFlow的数据包头具有通用字段,相关数据结构定义如下:
/* Header on all OpenFlow packets. */
struct ofp_header {
uint8_t version; /* OFP_VERSION. */
uint8_t type; /* One of the OFPT_ constants. */
uint16_t length; /* Length including this ofp_header. */
uint32_t xid; /* Transaction id associated with this packet.
Replies use the same id as was in the request
to facilitate pairing. */
};
OFPT_HELLO
/* OFPT_HELLO. This message has an empty body, but implementations must
* ignore any data included in the body, to allow for future extensions. */
struct ofp_hello {
struct ofp_header header;
};
OFPT_FEATURES_REQUEST
格式与上述ofp_header结构体中数据相同
OFPT_SET_CONFIG
/* Switch configuration. */
struct ofp_switch_config {
struct ofp_header header;
uint16_t flags; /* OFPC_* flags. */
uint16_t miss_send_len; /* Max bytes of new flow that datapath should
send to the controller. */
};
OFPT_FEATURES_REPLY
/* Description of a physical port */
struct ofp_phy_port {
uint16_t port_no;
uint8_t hw_addr[OFP_ETH_ALEN];
char name[OFP_MAX_PORT_NAME_LEN]; /* Null-terminated */
uint32_t config; /* Bitmap of OFPPC_* flags. */
uint32_t state; /* Bitmap of OFPPS_* flags. */
/* Bitmaps of OFPPF_* that describe features. All bits zeroed if
* unsupported or unavailable. */
uint32_t curr; /* Current features. */
uint32_t advertised; /* Features being advertised by the port. */
uint32_t supported; /* Features supported by the port. */
uint32_t peer; /* Features advertised by peer. */
};
/* Switch features. */
struct ofp_switch_features {
struct ofp_header header;
uint64_t datapath_id; /* Datapath unique ID. The lower 48-bits are for
a MAC address, while the upper 16-bits are
implementer-defined. */
uint32_t n_buffers; /* Max packets buffered at once. */
uint8_t n_tables; /* Number of tables supported by datapath. */
uint8_t pad[3]; /* Align to 64-bits. */
/* Features. */
uint32_t capabilities; /* Bitmap of support "ofp_capabilities". */
uint32_t actions; /* Bitmap of supported "ofp_action_type"s. */
/* Port info.*/
struct ofp_phy_port ports[0]; /* Port definitions. The number of ports
is inferred from the length field in
the header. */
};
OFPT_PACKET_IN
struct ofp_packet_in {
struct ofp_header header;
uint32_t buffer_id; /* ID assigned by datapath. */
uint16_t total_len; /* Full length of frame. */
uint16_t in_port; /* Port on which frame was received. */
uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */
uint8_t pad;
uint8_t data[0]; /* Ethernet frame, halfway through 32-bit word,
so the IP header is 32-bit aligned. The
amount of data is inferred from the length
field in the header. Because of padding,
offsetof(struct ofp_packet_in, data) ==
sizeof(struct ofp_packet_in) - 2. */
};
OFPT_PACKET_OUT
/* Send packet (controller -> datapath). */
struct ofp_packet_out {
struct ofp_header header;
uint32_t buffer_id; /* ID assigned by datapath (-1 if none). */
uint16_t in_port; /* Packet's input port (OFPP_NONE if none). */
uint16_t actions_len; /* Size of action array in bytes. */
struct ofp_action_header actions[0]; /* Actions. */
/* uint8_t data[0]; */ /* Packet data. The length is inferred
from the length field in the header.
(Only meaningful if buffer_id == -1.) */
};
/* Action header that is common to all actions. The length includes the
* header and any padding used to make the action 64-bit aligned.
* NB: The length of an action *must* always be a multiple of eight. */
struct ofp_action_header {
uint16_t type; /* One of OFPAT_*. */
uint16_t len; /* Length of action, including this
header. This is the length of action,
including any padding to make it
64-bit aligned. */
uint8_t pad[4];
};
OFPT_FLOW_MOD
struct ofp_flow_mod {
struct ofp_header header;
struct ofp_match match; /* Fields to match */
uint64_t cookie; /* Opaque controller-issued identifier. */
/* Flow actions. */
uint16_t command; /* One of OFPFC_*. */
uint16_t idle_timeout; /* Idle time before discarding (seconds). */
uint16_t hard_timeout; /* Max time before discarding (seconds). */
uint16_t priority; /* Priority level of flow entry. */
uint32_t buffer_id; /* Buffered packet to apply to (or -1).
Not meaningful for OFPFC_DELETE*. */
uint16_t out_port; /* For OFPFC_DELETE* commands, require
matching entries to include this as an
output port. A value of OFPP_NONE
indicates no restriction. */
uint16_t flags; /* One of OFPFF_*. */
struct ofp_action_header actions[0]; /* The action length is inferred
from the length field in the
header. */
};
/* Fields to match against flows */
struct ofp_match {
uint32_t wildcards; /* Wildcard fields. */
uint16_t in_port; /* Input switch port. */
uint8_t dl_src[OFP_ETH_ALEN]; /* Ethernet source address. */
uint8_t dl_dst[OFP_ETH_ALEN]; /* Ethernet destination address. */
uint16_t dl_vlan; /* Input VLAN id. */
uint8_t dl_vlan_pcp; /* Input VLAN priority. */
uint8_t pad1[1]; /* Align to 64-bits */
uint16_t dl_type; /* Ethernet frame type. */
uint8_t nw_tos; /* IP ToS (actually DSCP field, 6 bits). */
uint8_t nw_proto; /* IP protocol or lower 8 bits of
* ARP opcode. */
uint8_t pad2[2]; /* Align to 64-bits */
uint32_t nw_src; /* IP source address. */
uint32_t nw_dst; /* IP destination address. */
uint16_t tp_src; /* TCP/UDP source port. */
uint16_t tp_dst; /* TCP/UDP destination port. */
};
struct ofp_action_header {
uint16_t type; /* One of OFPAT_*. */
uint16_t len; /* Length of action, including this
header. This is the length of action,
including any padding to make it
64-bit aligned. */
uint8_t pad[4];
};
标签:struct,OpenFlow,实践,header,ofp,uint16,实验,交换机,net
From: https://www.cnblogs.com/calsk/p/16728806.html