OVS流表转发DHCP流量

24 篇文章 1 订阅
11 篇文章 7 订阅

DHCP协议及报文

动态主机配置协议(DHCP)是一种基于UDP协议且仅限于在局域网内部使用的网络协议,目的就是为了减轻TCP/IP网络的规划、管理和维护的负担,为局域网内部的设备分配IP地址、子网掩码、网关、DNS地址等网络信息。
DHCP功能分为两个部份:一个是服务器端,端口号67 ,而另一个是客户端,端口号68

DHCP的8种报文:

①:DHCP DISCOVER:这是 DHCP 客户端首次登录网络时进行 DHCP 过程的第一个报文,用来寻找 DHCP 服务器。
②:DHCP OFFER:DHCP服务器用来响应DHCP,DISCOVER报文,此报文携带了各种配置信息。
③:DHCP REQUEST:客户端初始化后,发送广播的 DHCP REQUEST 报文来回应服务器的 DHCP OFFER 报文。客户端重启初始化后,发送广播的 DHCP REQUEST 报文来确认先前被分配的 IP 地址等配置信息。当客户端已经和某个 IP 地址绑定后,发送 DHCP REQUEST 报文来延长 IP 地址的租期。
④:DHCP ACK:服务器对客户端的 DHCP REQUEST 报文的确认响应报文,客户端收到此报文后,才真正获得了 IP 地址和相关的配置信息。
⑤:DHCP NAK:服务器对客户端的 DHCP REQUEST 报文的拒绝响应报文,比如服务器对客户端分配的 IP 地址已超过使用租借期限或者由于某些原因无法正常分配 IP 地址,则发送 DHCP NAK 报文作为应答。
⑥:DHCP DECLINE:当客户端发现服务器分配给它的 IP 地址发生冲突时会通过发送此报文来通知服务器,并且会重新向服务器申请地址。
⑦:DHCP RELEASE:客户端可通过发送此报文主动释放服务器分配给它的 IP 地址,当服务器收到此报文后,可将这个 IP 地址分配给其它的客户端。
⑧:DHCP INFORM:客户端已经获得了 IP 地址,发送此报文的目的是为了从服务器获得其他的一些网络配置信息,比如网关地址、DNS 服务器地址等。

DHCP分配过程

1、DHCP客户端通过广播方式发送DHCP DISCOVER请求报文来寻找网络中的DHCP服务器,源端口68,目的端口67。
2、DHCP服务端会Ping即将分配的ip地址
3、DHCP服务器收到DHCP DISCOVER请求报文后,会从自己的地址池中选择一个合适的IP地址,把IP地址,子网掩码,网关,DNS,租约相关的内容还有客户端的MAC地址封装在DHCP OFFER报文中,通过广播方式发送给客户端,网络内的所有客户端根据封装在DHCP OFFER报文中的MAC地址来决定是否接收此报文。源端口67,目的端口68
4、DHCP客户端收到DHCP OFFER报文后,会再通过广播方式发送一个DHCP REQUEST报文,但是在requested address字段包含了OFFER应答报文中分配的IP地址,DHCP服务器地址和DHCP服务器名。源端口68,目的端口67。
5、DHCP服务器在收到客户端的REQUEST报文后,确认将此IP地址分配给客户端,会以广播方式返回一个DHCP ACK确认报文,确认不能把此IP地址分配给客户端则返回一个DHCP NAK确认报文。源端口67,目的端口68
6、DHCP客户端在收到服务器的ACK确认报文后,会以广播方式发送免费的ARP报文,该报文中源IP和目的IP都是本机的IP地址,源MAC是本机的MAC,目的MAC是广播MAC,探测网络内是否有主机使用服务器分给自己的IP地址,如果在规定时间内没有收到回应,则正是使用该地址,否则,客户端会继续发送DHCP DECLINE报文给DHCP服务器,重新申请IP地址

DHCP是单播还是组播

从DHCP Server回复的报文是单播还是广播由DHCP Client决定,有些IP协议栈在完成IP地址的配置前,是不会接收任何单播IP报文的,只会接收广播IP报文,即Dst IP = 255.255.255.255,会在DHCP Discovery / Request报文的Flags里明确告知服务器,通过设置“BROADCAST flag = 1”
如果协议栈在初始化时,可以接收单播IP报文,请在DHCP Discovery / Request报文的Flags里明确告知服务器,通过设置“BROADCAST flag = 0”,那么服务器就使用单播来和客户端通信。
在这里插入图片描述

搭建环境验证DHCP获取IP和释放IP

在这里插入图片描述

# 创建netns代替虚拟机
ip netns add ns100

 # 创建一对veth pair一端veth0,另一端ovs-veth0
ip l a veth0 type veth peer name ovs-veth0

 # veth0插入netns
ip l s veth0 netns ns100

#创建br-int网桥
ovs-vsctl add-br br-int

# ovs-veth0插入到br-int
ovs-vsctl add-port br-int ovs-veth0
ip l s ovs-veth0 up

# 在br-int网桥上创建dhcp端口 
ovs-vsctl add-port br-int dhcp1 -- set interface dhcp1 type=internal

#给dhcp端口配置ip,可通过ip addr delete 192.168.1.1 dev dhcp1删除
ifconfig dhcp1 192.168.1.1

#通过dnsmasq启动dhcp服务,给dhcp server配置连接池
dnsmasq --bind-interfaces --except-interface=lo --interface dhcp1 --dhcp-range 192.168.1.2,192.168.1.10

# 从dhcp client到server的广播流量
ovs-ofctl add-flow br-int "table=0,priority=100,udp,nw_dst=255.255.255.255,tp_src=68,tp_dst=67,actions=output:dhcp1"
# 从dhcp client到server的单播流量
ovs-ofctl add-flow br-int "table=0,priority=100,udp,nw_dst=192.168.1.1,tp_src=68,tp_dst=67,actions=output:dhcp1"
# 从dhcp server到dhcp client的单播和广播流量,因为源ip唯一
ovs-ofctl add-flow br-int "table=0,priority=100,udp,nw_src=192.168.1.1,tp_src=67,tp_dst=68,actions=output:ovs-veth0"


# 先看一下当前netns的ip
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
11: veth0@if10: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 6e:e8:3d:79:44:4b brd ff:ff:ff:ff:ff:ff link-netnsid 0

# 通过dhclient获取ip
$ ip netns exec ns100 dhclient veth0

# 在dhcp1口抓包
10:05:40.525512 6e:e8:3d:79:44:4b > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 342: (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from 6e:e8:3d:79:44:4b, length 300, xid 0x4ed34737, Flags [none] (0x0000)
          Client-Ethernet-Address 6e:e8:3d:79:44:4b
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Discover
            Requested-IP Option 50, length 4: 192.168.1.8
            Hostname Option 12, length 6: "ubuntu"
            Parameter-Request Option 55, length 13:
              Subnet-Mask, BR, Time-Zone, Default-Gateway
              Domain-Name, Domain-Name-Server, Option 119, Hostname
              Netbios-Name-Server, Netbios-Scope, MTU, Classless-Static-Route
              NTP
10:05:40.525669 d6:bd:3e:83:49:f9 > 6e:e8:3d:79:44:4b, ethertype IPv4 (0x0800), length 62: (tos 0x0, ttl 64, id 25589, offset 0, flags [DF], proto ICMP (1), length 48)
    192.168.1.1 > 192.168.1.8: ICMP echo request, id 56407, seq 0, length 28

10:05:43.529494 d6:bd:3e:83:49:f9 > 6e:e8:3d:79:44:4b, ethertype IPv4 (0x0800), length 342: (tos 0xc0, ttl 64, id 43770, offset 0, flags [none], proto UDP (17), length 328)
    192.168.1.1.67 > 192.168.1.8.68: [bad udp cksum 0x849f -> 0x4b80!] BOOTP/DHCP, Reply, length 300, xid 0x4ed34737, Flags [none] (0x0000)
          Your-IP 192.168.1.8
          Server-IP 192.168.1.1
          Client-Ethernet-Address 6e:e8:3d:79:44:4b
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Offer
            Server-ID Option 54, length 4: 192.168.1.1
            Lease-Time Option 51, length 4: 3600
            RN Option 58, length 4: 1800
            RB Option 59, length 4: 3150
            Subnet-Mask Option 1, length 4: 255.255.255.0
            BR Option 28, length 4: 192.168.1.255
            Default-Gateway Option 3, length 4: 192.168.1.1
            Domain-Name-Server Option 6, length 4: 192.168.1.1

10:05:43.529846 6e:e8:3d:79:44:4b > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 342: (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from 6e:e8:3d:79:44:4b, length 300, xid 0x4ed34737, secs 3, Flags [none] (0x0000)
          Client-Ethernet-Address 6e:e8:3d:79:44:4b
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Request
            Server-ID Option 54, length 4: 192.168.1.1
            Requested-IP Option 50, length 4: 192.168.1.8
            Hostname Option 12, length 6: "ubuntu"
            Parameter-Request Option 55, length 13:
              Subnet-Mask, BR, Time-Zone, Default-Gateway
              Domain-Name, Domain-Name-Server, Option 119, Hostname
              Netbios-Name-Server, Netbios-Scope, MTU, Classless-Static-Route
              NTP
10:05:43.532087 d6:bd:3e:83:49:f9 > 6e:e8:3d:79:44:4b, ethertype IPv4 (0x0800), length 342: (tos 0xc0, ttl 64, id 43772, offset 0, flags [none], proto UDP (17), length 328)
    192.168.1.1.67 > 192.168.1.8.68: [bad udp cksum 0x849f -> 0xfc11!] BOOTP/DHCP, Reply, length 300, xid 0x4ed34737, secs 3, Flags [none] (0x0000)
          Your-IP 192.168.1.8
          Server-IP 192.168.1.1
          Client-Ethernet-Address 6e:e8:3d:79:44:4b
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: ACK
            Server-ID Option 54, length 4: 192.168.1.1
            Lease-Time Option 51, length 4: 3600
            RN Option 58, length 4: 1800
            RB Option 59, length 4: 3150
            Subnet-Mask Option 1, length 4: 255.255.255.0
            BR Option 28, length 4: 192.168.1.255
            Default-Gateway Option 3, length 4: 192.168.1.1
            Domain-Name-Server Option 6, length 4: 192.168.1.1
            Hostname Option 12, length 6: "ubuntu"
10:05:48.669095 d6:bd:3e:83:49:f9 > 6e:e8:3d:79:44:4b, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has 192.168.1.8 tell 192.168.1.1, length 28
10:05:48.669388 6e:e8:3d:79:44:4b > d6:bd:3e:83:49:f9, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Reply 192.168.1.8 is-at 6e:e8:3d:79:44:4b, length 28

# 查看获取ip情况
$ ip netns exec ns100 ip a

1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
11: veth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 6e:e8:3d:79:44:4b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.1.8/24 brd 192.168.1.255 scope global dynamic veth0
       valid_lft 3594sec preferred_lft 3594sec
    inet6 fe80::6ce8:3dff:fe79:444b/64 scope link
       valid_lft forever preferred_lft forever
       
# 释放ip
 ip netns exec ns100 dhclient -r
Killed old client process

# dhcp1口抓包,抓到release报文
 tcpdump -i dhcp1 -nn -vv -e
tcpdump: listening on dhcp1, link-type EN10MB (Ethernet), capture size 262144 bytes
10:04:05.215678 6e:e8:3d:79:44:4b > d6:bd:3e:83:49:f9, ethertype IPv4 (0x0800), length 342: (tos 0x0, ttl 64, id 57498, offset 0, flags [DF], proto UDP (17), length 328)
    192.168.1.8.68 > 192.168.1.1.67: [udp sum ok] BOOTP/DHCP, Request from 6e:e8:3d:79:44:4b, length 300, xid 0x78cfc423, Flags [none] (0x0000)
          Client-IP 192.168.1.8
          Client-Ethernet-Address 6e:e8:3d:79:44:4b
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message Option 53, length 1: Release
            Server-ID Option 54, length 4: 192.168.1.1
            Hostname Option 12, length 6: "ubuntu"
DHCP Client请求IP

通过抓包可以发现,DHCP Server在收到discovery报文后会发送免费arp进行冲突检测,检测要分配的ip是否被其他主机占用,之后会发送icmp包检测DHCP Client是否占用,之后单播回复,因为client在discovery报文里已设置支持单播,而client发送request报文是当网络中有多个DHCP Server时,会同时给client发送IP,而client选择其中一个后会发reuest通知所有DHCP Server自己使用某个DHCP Server,只有被选择的DHCP Server会回复client
在这里插入图片描述

DHCP Client释放IP

当dhcp租约到期时client主动单播发送release报文给server
在这里插入图片描述

OVN验证DHCP功能

在这里插入图片描述

#创建lr
ovn-nbctl lr-add lr
ovn-nbctl lrp-add lr lrp fe:fe:fe:fe:fe:aa 192.168.0.1/24

#创建ls,连接上lr
ovn-nbctl ls-add ls
ovn-nbctl lsp-add ls lsp
ovn-nbctl lsp-set-type lsp router
ovn-nbctl lsp-set-addresses lsp fe:fe:fe:fe:fe:aa
ovn-nbctl lsp-set-options lsp router-port=lrp

#创建vm口动态从dhcp获取ip,同时要制定ip范围和保留ip段
ovn-nbctl lsp-add ls ls-vm
ovn-nbctl lsp-set-addresses ls-vm "fe:fe:fe:fe:fe:cc dynamic"
ovn-nbctl set Logical-switch ls other_config:subnet="192.168.0.0/24" other_config:exclude_ips="192.168.0.1..192.168.0.5"

#在worker节点创建vm
ip netns add vm
ovs-vsctl add-port br-int vm -- set interface vm type=internal
ip link set vm address fe:fe:fe:fe:fe:cc
ip link set vm netns vm
ip netns exec vm ip link set vm up
ovs-vsctl set Interface vm external_ids:iface-id=ls-vm

#配置dhcp,uuid为创建DHCP_Options返回的值
ovn-nbctl create DHCP_Options cidr=192.168.0.0/24 options=""server_id"="192.168.0.1" "server_mac"="fe:fe:fe:fe:fe:aa" "lease_time"="3600" "router"="192.168.0.1" "dns_server"="172.16.0.254""
ovn-nbctl lsp-set-dhcpv4-options ls-vm 1a1a9ee7-6b51-4231-8ec5-9d6135dc6233

#查看北向数据库
ovn-nbctl show
switch 48f1921d-42f6-44e8-95a7-801c0bdc4e02 (ls)
port lsp
type: router
addresses: ["fe:fe:fe:fe:fe:aa"]
router-port: lrp
port ls-vm
addresses: ["fe:fe:fe:fe:fe:cc dynamic"]
router e9e827bd-b3aa-47b9-8378-c9cc5d814309 (lr)
port lrp
mac: "fe:fe:fe:fe:fe:aa"
networks: ["192.168.0.1/24"]

#查看交换机ls端口信息,可以看到ls-vm口连接到dhcp池
ovn-nbctl list logical_switch_port
_uuid               : 2ae07696-954d-41f0-b84b-aba549a0a22c
addresses           : ["fe:fe:fe:fe:fe:aa"]
dhcpv4_options      : []
dhcpv6_options      : []
dynamic_addresses   : []
enabled             : []
external_ids        : {}
ha_chassis_group    : []
name                : lsp
options             : {router-port=lrp}
parent_name         : []
port_security       : []
tag                 : []
tag_request         : []
type                : router
up                  : true
_uuid               : 444ad243-7f82-4343-b6ed-6d5cbd525198
addresses           : ["fe:fe:fe:fe:fe:cc dynamic"]
dhcpv4_options      : 49526bdf-8d5d-40f6-b447-78ca424696e7
dhcpv6_options      : []
dynamic_addresses   : []
enabled             : []
external_ids        : {}
ha_chassis_group    : []
name                : ls-vm
options             : {}
parent_name         : []
port_security       : []
tag                 : []
tag_request         : []
type                : ""
up                  : true

#dhcp功能验证,看到vm绑定ip是192.168.0.6,因为前5个ip保留
ip netns exec vm dhclient -v vm
Internet Systems Consortium DHCP Client 4.4.1
Copyright 2004-2018 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/
Listening on LPF/vm/fe:fe:fe:fe:fe:cc
Sending on   LPF/vm/fe:fe:fe:fe:fe:cc
Sending on   Socket/fallback
DHCPDISCOVER on vm to 255.255.255.255 port 67 interval 3 (xid=0x4428c70d)
DHCPOFFER of 192.168.0.6 from 192.168.0.1
DHCPREQUEST for 192.168.0.6 on vm to 255.255.255.255 port 67 (xid=0xdc72844)
DHCPACK of 192.168.0.6 from 192.168.0.1 (xid=0x4428c70d)
mv: cannot move '/etc/resolv.conf.dhclient-new.1798480' to '/etc/resolv.conf': Device or resource busy
bound to 192.168.0.6 -- renewal in 1695 seconds.

#查看Logical Flow
ovn-sbctl lflow-list ls
Datapath: "ls" (c33e860d-fd6b-4091-98ed-41a45d838bec)  Pipeline: ingress
table=0 (ls_in_port_sec_l2  ), priority=100  , match=(eth.src[40]), action=(drop;)
table=0 (ls_in_port_sec_l2  ), priority=100  , match=(vlan.present), action=(drop;)
table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "ls-vm"), action=(next;)
table=0 (ls_in_port_sec_l2  ), priority=50   , match=(inport == "lsp"), action=(next;)
table=1 (ls_in_port_sec_ip  ), priority=0    , match=(1), action=(next;)
table=2 (ls_in_port_sec_nd  ), priority=0    , match=(1), action=(next;)
table=3 (ls_in_lookup_fdb   ), priority=0    , match=(1), action=(next;)
table=4 (ls_in_put_fdb      ), priority=0    , match=(1), action=(next;)
table=5 (ls_in_pre_acl      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(next;)
table=5 (ls_in_pre_acl      ), priority=0    , match=(1), action=(next;)
table=6 (ls_in_pre_lb       ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(next;)
table=6 (ls_in_pre_lb       ), priority=110  , match=(eth.mcast), action=(next;)
table=6 (ls_in_pre_lb       ), priority=110  , match=(ip && inport == "lsp"), action=(next;)
table=6 (ls_in_pre_lb       ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
table=6 (ls_in_pre_lb       ), priority=0    , match=(1), action=(next;)
table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[2] == 1 && ip4 && sctp), action=(reg1 = ip4.dst; reg2[0..15] = sctp.dst; ct_lb;)
table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[2] == 1 && ip4 && tcp), action=(reg1 = ip4.dst; reg2[0..15] = tcp.dst; ct_lb;)
table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[2] == 1 && ip4 && udp), action=(reg1 = ip4.dst; reg2[0..15] = udp.dst; ct_lb;)
table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[2] == 1 && ip6 && sctp), action=(xxreg1 = ip6.dst; reg2[0..15] = sctp.dst; ct_lb;)
table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[2] == 1 && ip6 && tcp), action=(xxreg1 = ip6.dst; reg2[0..15] = tcp.dst; ct_lb;)
table=7 (ls_in_pre_stateful ), priority=120  , match=(reg0[2] == 1 && ip6 && udp), action=(xxreg1 = ip6.dst; reg2[0..15] = udp.dst; ct_lb;)
table=7 (ls_in_pre_stateful ), priority=110  , match=(reg0[2] == 1), action=(ct_lb;)
table=7 (ls_in_pre_stateful ), priority=100  , match=(reg0[0] == 1), action=(ct_next;)
table=7 (ls_in_pre_stateful ), priority=0    , match=(1), action=(next;)
table=8 (ls_in_acl_hint     ), priority=65535, match=(1), action=(next;)
table=9 (ls_in_acl          ), priority=65535, match=(1), action=(next;)
table=10(ls_in_qos_mark     ), priority=0    , match=(1), action=(next;)
table=11(ls_in_qos_meter    ), priority=0    , match=(1), action=(next;)
table=12(ls_in_lb           ), priority=0    , match=(1), action=(next;)
table=13(ls_in_acl_after_lb ), priority=0    , match=(1), action=(next;)
table=14(ls_in_stateful     ), priority=100  , match=(reg0[1] == 1 && reg0[13] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;)
table=14(ls_in_stateful     ), priority=100  , match=(reg0[1] == 1 && reg0[13] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;)
table=14(ls_in_stateful     ), priority=0    , match=(1), action=(next;)
table=15(ls_in_pre_hairpin  ), priority=0    , match=(1), action=(next;)
table=16(ls_in_nat_hairpin  ), priority=0    , match=(1), action=(next;)
table=17(ls_in_hairpin      ), priority=0    , match=(1), action=(next;)
table=18(ls_in_arp_rsp      ), priority=100  , match=(arp.tpa == 192.168.0.6 && arp.op == 1 && inport == "ls-vm"), action=(next;)
table=18(ls_in_arp_rsp      ), priority=50   , match=(arp.tpa == 192.168.0.6 && arp.op == 1), action=(eth.dst = eth.src; eth.src = fe:fe:fe:fe:fe:cc; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = fe:fe:fe:fe:fe:cc; arp.tpa = arp.spa; arp.spa = 192.168.0.6; outport = inport; flags.loopback = 1; output;)
table=18(ls_in_arp_rsp      ), priority=0    , match=(1), action=(next;)
table=19(ls_in_dhcp_options ), priority=100  , match=(inport == "ls-vm" && eth.src == fe:fe:fe:fe:fe:cc && ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 192.168.0.6, dns_server = 172.16.0.254, lease_time = 3600, netmask = 255.255.255.0, router = 192.168.0.1, server_id = 192.168.0.1); next;)
table=19(ls_in_dhcp_options ), priority=100  , match=(inport == "ls-vm" && eth.src == fe:fe:fe:fe:fe:cc && ip4.src == 192.168.0.6 && ip4.dst == {192.168.0.1, 255.255.255.255} && udp.src == 68 && udp.dst == 67), action=(reg0[3] = put_dhcp_opts(offerip = 192.168.0.6, dns_server = 172.16.0.254, lease_time = 3600, netmask = 255.255.255.0, router = 192.168.0.1, server_id = 192.168.0.1); next;)
table=19(ls_in_dhcp_options ), priority=0    , match=(1), action=(next;)
table=20(ls_in_dhcp_response), priority=100  , match=(inport == "ls-vm" && eth.src == fe:fe:fe:fe:fe:cc && ip4 && udp.src == 68 && udp.dst == 67 && reg0[3]), action=(eth.dst = eth.src; eth.src = fe:fe:fe:fe:fe:aa; ip4.src = 192.168.0.1; udp.src = 67; udp.dst = 68; outport = inport; flags.loopback = 1; output;)
table=20(ls_in_dhcp_response), priority=0    , match=(1), action=(next;)
table=21(ls_in_dns_lookup   ), priority=0    , match=(1), action=(next;)
table=22(ls_in_dns_response ), priority=0    , match=(1), action=(next;)
table=23(ls_in_external_port), priority=0    , match=(1), action=(next;)
table=24(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac), action=(handle_svc_check(inport);)
table=24(ls_in_l2_lkup      ), priority=80   , match=(flags[1] == 0 && arp.op == 1 && arp.tpa == 192.168.0.1), action=(clone {outport = "lsp"; output; }; outport = "_MC_flood_l2"; output;)
table=24(ls_in_l2_lkup      ), priority=80   , match=(flags[1] == 0 && nd_ns && nd.target == fe80::fcfe:feff:fefe:feaa), action=(clone {outport = "lsp"; output; }; outport = "_MC_flood_l2"; output;)
table=24(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {fe:fe:fe:fe:fe:aa} && (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood_l2"; output;)
table=24(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = "_MC_flood"; output;)
table=24(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == fe:fe:fe:fe:fe:aa), action=(outport = "lsp"; output;)
table=24(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == fe:fe:fe:fe:fe:cc), action=(outport = "ls-vm"; output;)
table=24(ls_in_l2_lkup      ), priority=0    , match=(1), action=(outport = get_fdb(eth.dst); next;)
table=25(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), action=(drop;)
table=25(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
Datapath: "ls" (c33e860d-fd6b-4091-98ed-41a45d838bec)  Pipeline: egress
table=0 (ls_out_pre_lb      ), priority=110  , match=(eth.mcast), action=(next;)
table=0 (ls_out_pre_lb      ), priority=110  , match=(eth.src == $svc_monitor_mac), action=(next;)
table=0 (ls_out_pre_lb      ), priority=110  , match=(ip && outport == "lsp"), action=(next;)
table=0 (ls_out_pre_lb      ), priority=110  , match=(nd || nd_rs || nd_ra || mldv1 || mldv2), action=(next;)
table=0 (ls_out_pre_lb      ), priority=0    , match=(1), action=(next;)
table=1 (ls_out_pre_acl     ), priority=110  , match=(eth.src == $svc_monitor_mac), action=(next;)
table=1 (ls_out_pre_acl     ), priority=0    , match=(1), action=(next;)
table=2 (ls_out_pre_stateful), priority=110  , match=(reg0[2] == 1), action=(ct_lb;)
table=2 (ls_out_pre_stateful), priority=100  , match=(reg0[0] == 1), action=(ct_next;)
table=2 (ls_out_pre_stateful), priority=0    , match=(1), action=(next;)
table=3 (ls_out_acl_hint    ), priority=65535, match=(1), action=(next;)
table=4 (ls_out_acl         ), priority=65535, match=(1), action=(next;)
table=4 (ls_out_acl         ), priority=34000, match=(outport == "ls-vm" && eth.src == fe:fe:fe:fe:fe:aa && ip4.src == 192.168.0.1 && udp && udp.src == 67 && udp.dst == 68), action=(next;)
table=5 (ls_out_qos_mark    ), priority=0    , match=(1), action=(next;)
table=6 (ls_out_qos_meter   ), priority=0    , match=(1), action=(next;)
table=7 (ls_out_stateful    ), priority=100  , match=(reg0[1] == 1 && reg0[13] == 0), action=(ct_commit { ct_label.blocked = 0; }; next;)
table=7 (ls_out_stateful    ), priority=100  , match=(reg0[1] == 1 && reg0[13] == 1), action=(ct_commit { ct_label.blocked = 0; ct_label.label = reg3; }; next;)
table=7 (ls_out_stateful    ), priority=0    , match=(1), action=(next;)
table=8 (ls_out_port_sec_ip ), priority=0    , match=(1), action=(next;)
table=9 (ls_out_port_sec_l2 ), priority=100  , match=(eth.mcast), action=(output;)
table=9 (ls_out_port_sec_l2 ), priority=50   , match=(outport == "ls-vm"), action=(output;)
table=9 (ls_out_port_sec_l2 ), priority=50   , match=(outport == "lsp"), action=(output;)


可以看到table19里交换机收到dhcp流量匹配inport来自虚拟机,源mac是虚拟机mac,源ip是0.0.0.0,目的ip是255.255.255.255,源端口是68,目的端口是67,上送到控制器,控制器将数据包的源mac设置为网关mac,目的mac改为dhcp request包的源mac,源ip改为网关ip,修改源端口67,目的端口68,output口修改为input口在table20里返回。缺点是不支持对分配的ip进行冲突监测。

在vm抓包
ip netns exec vm tcpdump -i vm -nn -vv -e
tcpdump: listening on vm, link-type EN10MB (Ethernet), snapshot length 262144 bytes
08:01:50.669665 fe:fe:fe:fe:fe:cc > ff:ff:ff:ff:ff:ff, ethertype IPv4 (0x0800), length 342: (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 328)
    0.0.0.0.68 > 255.255.255.255.67: [udp sum ok] BOOTP/DHCP, Request from fe:fe:fe:fe:fe:cc, length 300, xid 0xcdd76e4a, Flags [none] (0x0000)
          Client-Ethernet-Address fe:fe:fe:fe:fe:cc
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message (53), length 1: Request
            Requested-IP (50), length 4: 192.168.0.6
            Hostname (12), length 10: "ovn-worker"
            Parameter-Request (55), length 13:
              Subnet-Mask (1), BR (28), Time-Zone (2), Default-Gateway (3)
              Domain-Name (15), Domain-Name-Server (6), Unknown (119), Hostname (12)
              Netbios-Name-Server (44), Netbios-Scope (47), MTU (26), Classless-Static-Route (121)
              NTP (42)
08:01:50.670339 fe:fe:fe:fe:fe:aa > fe:fe:fe:fe:fe:cc, ethertype IPv4 (0x0800), length 324: (tos 0x10, ttl 128, id 0, offset 0, flags [none], proto UDP (17), length 310)
    192.168.0.1.67 > 192.168.0.6.68: [no cksum] BOOTP/DHCP, Reply, length 282, xid 0xcdd76e4a, Flags [none] (0x0000)
          Your-IP 192.168.0.6
          Client-Ethernet-Address fe:fe:fe:fe:fe:cc
          Vendor-rfc1048 Extensions
            Magic Cookie 0x63825363
            DHCP-Message (53), length 1: ACK
            Domain-Name-Server (6), length 4: 172.16.0.254
            Lease-Time (51), length 4: 3600
            Subnet-Mask (1), length 4: 255.255.255.0
            Default-Gateway (3), length 4: 192.168.0.1
            Server-ID (54), length 4: 192.168.0.1


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值