Message ID | 20240529232759.380537-1-witu@nvidia.com |
---|---|
State | Changes Requested |
Headers | show |
Series | [ovs-dev,v5] route-table: Add support for v4 via v6 route. | expand |
Context | Check | Description |
---|---|---|
ovsrobot/apply-robot | success | apply and check: success |
ovsrobot/github-robot-_Build_and_Test | fail | github build: failed |
ovsrobot/intel-ovs-compilation | success | test: success |
On 5/30/24 01:27, William Tu wrote: > Add route-table support for ipv4 dst via ipv6. One use case is BGP > unnumbered, a mechanism that establishes peering sessions without the > need to explicitly configure IPv4 addresses on the interfaces involved > in the peering. Without using IPv4 address assignments, it uses > link-local IPv6 addresses of the directly connected neighbors for > peering purposes. For example, BGP might install the following route: > $ ip route get 100.87.18.3 > 100.87.18.3 via inet6 fe80::920a:84ff:fe9e:9570 \ > dev br-phy src 100.87.18.6 > > Note that the v6 addr fe80::920a:84ff:fe9e:9570 is not being used in > the packet header, but only used for lookup the out dev br-phy. > Currently OVS can only support either all-ipv4 or all-ipv6, the patch > adds support for such use case. > > Reported-at: https://mail.openvswitch.org/pipermail/ovs-discuss/2024-January/052908.html > Acked-by: Simon Horman <horms@ovn.org> > Signed-off-by: William Tu <witu@nvidia.com> > --- > v5: fix minor CI failure > v4: feedback from Ilya > - add route del test case, wrap around test width > - not set neighbor cache manually > - on br-phy, use /32 on address in steead of /24 > compare v3 and v4 > https://github.com/williamtu/ovs/compare/router..router-v4 > v3: add vxlan test, remove rfc > v2: fix CI error > --- <snip> > diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at > index 508737c53ec6..7266f0990570 100644 > --- a/tests/tunnel-push-pop.at > +++ b/tests/tunnel-push-pop.at > @@ -196,6 +196,69 @@ OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 100022eb0000000120000237 | wc -l` > OVS_VSWITCHD_STOP > AT_CLEANUP > > +AT_SETUP([tunnel_push_pop - v4 via v6 route]) > + > +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) > +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) > +AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=vxlan \ > + options:remote_ip=1.1.2.92 options:key=123 ofport_request=1\ > + ], [0]) > + > +AT_CHECK([ovs-appctl dpif/show], [0], [dnl > +dummy@ovs-dummy: hit:0 missed:0 > + br0: > + br0 65534/100: (dummy-internal) > + p0 1/1: (dummy) > + int-br: > + int-br 65534/2: (dummy-internal) > + t1 1/4789: (vxlan: key=123, remote_ip=1.1.2.92) > +]) > + > +AT_CHECK([ovs-ofctl add-flow br0 action=normal]) > + > +dnl Setup dummy interface IP addresses. > +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/32], [0], [OK > +]) > +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/64], [0], [OK > +]) > +dnl Add a static v4 via v6 route > +AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/32 br0 2001:cafe::10 src=1.1.2.89], [0], [OK > +]) > + > +AT_CHECK([ovs-appctl ovs/route/show | grep br0 | sort], [0], [dnl > +Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local > +Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local > +User: 1.1.2.92/32 dev br0 GW 2001:cafe::10 SRC 1.1.2.89 > +]) > + > +dnl Check ARP Snoop > +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(100),dnl > +eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),dnl > +arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)']) This is still not a correct test, we would never receive an ARP from an IPv6-only network. This must be an IPv6 NA packet instead. All in all, I'd expect the following test to work without modifications (unless I mistyped something): --- AT_SETUP([tunnel_push_pop - v4 via v6 route]) OVS_VSWITCHD_START( [add-port br0 p0 \ -- set Interface p0 type=dummy ofport_request=1 \ other-config:hwaddr=aa:55:aa:55:00:00]) AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg]) AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy]) AT_CHECK([ovs-vsctl add-port int-br t2 \ -- set Interface t2 type=geneve \ options:remote_ip=1.1.2.92 \ options:key=123 ofport_request=2]) dnl Setup IP addresses. AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/32], [0], [OK ]) AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/64], [0], [OK ]) dnl Adding a static v4 via v6 route. AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/32 br0 2001:cafe::10 src=1.1.2.88], [0], [OK ]) dnl Checking that a local route for added IP was successfully installed. AT_CHECK([ovs-appctl ovs/route/show | grep br0 | sort], [0], [dnl Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local User: 1.1.2.92/32 dev br0 GW 2001:cafe::10 SRC 1.1.2.88 ]) AT_CHECK([ovs-ofctl add-flow br0 action=normal]) AT_CHECK([ovs-ofctl add-flow int-br action=normal]) AT_CHECK([ovs-vsctl -- set Interface p0 options:tx_pcap=p0.pcap]) dnl Check that v4-over-v6 route is used in the trace and that a tunnel neighbor dnl lookup miss generates ND and not an ARP. AT_CHECK([ovs-appctl ofproto/trace int-br in_port=LOCAL \ | grep -E 'tunnel|neighbor|actions'], [0], [dnl -> output to native tunnel -> tunneling to 2001:cafe::10 via br0 -> neighbor cache miss for 2001:cafe::10 on bridge br0, sending ND request Datapath actions: drop ]) dnl Check that the correct Neighbor Solicitation was sent out via p0. m4_define([ND_NS_PACKET], [m4_joinall([,], [eth_src=aa:55:aa:55:00:00,eth_dst=33:33:ff:00:00:10,eth_type=0x86dd], [ipv6_src=2001:cafe::88,ipv6_dst=ff02::1:ff00:10], [nw_proto=58,nw_ttl=255,nw_frag=no], [icmpv6_type=135,icmpv6_code=0], [nd_target=2001:cafe::10,nd_options_type=1,nd_sll=aa:55:aa:55:00:00])]) OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap \ | grep -c "$(ovs-ofctl compose-packet --bare 'ND_NS_PACKET')") -eq 1]) dnl Now send a Neighbor Advertisement from p0 which has two effects: dnl 1. The neighbor cache will learn that 2001:cafe::10 is at f8:bc:12:44:34:b6. dnl 2. The br0 mac learning will learn that f8:bc:12:44:34:b6 is on p0. AT_CHECK([ovs-appctl netdev-dummy/receive p0 dnl 'recirc_id(0),in_port(1),dnl eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),dnl ipv6(src=2001:cafe::10,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),dnl icmpv6(type=136,code=0),dnl nd(target=2001:cafe::10,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)' ]) dnl Check that v4-over-v6 route is used in the trace and the tunnel is working. AT_CHECK([ovs-appctl ofproto/trace int-br in_port=LOCAL \ | grep -E 'tunnel|neighbor|actions'], [0], [dnl -> output to native tunnel -> tunneling to 2001:cafe::10 via br0 -> tunneling from aa:55:aa:55:00:00 1.1.2.88 to f8:bc:12:44:34:b6 2001:cafe::10 Datapath actions: tnl_push(tnl_port(6081),header(size=50,type=5,dnl eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),dnl ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),dnl udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100)),1 ]) dnl Now check that the packet is actually encapsulated and delivered. packet=50540000000a5054000000091234 eth=f8bc124434b6aa55aa5500000800 ip4=450000320000400040113406010102580101025c dnl Source port is based on a packet hash, so it may differ depending on the dnl compiler flags and CPU type. Masked with '....'. udp=....17c1001e0000 geneve=0000655800007b00 encap=${eth}${ip4}${udp}${geneve} dnl Output to the tunnel from the int-br internal port. dnl Checking that the packet arrived and it was correctly encapsulated. AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"]) OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 1]) dnl Sending again to exercise the non-miss upcall path. AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"]) OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 2]) dnl Finally, checking that the datapath flow is also correct. AT_CHECK([ovs-appctl dpctl/dump-flows | grep tnl_push \ | strip_ufid | strip_used], [0], [dnl recirc_id(0),in_port(2),packet_type(ns=0,id=0),dnl eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234), dnl packets:1, bytes:14, used:0.0s, dnl actions:tnl_push(tnl_port(6081),header(size=50,type=5,dnl eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),dnl ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),dnl udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100)),1 ]) OVS_VSWITCHD_STOP AT_CLEANUP --- With the current version of a patch it fails on the tunnel neighbor lookup because it looks for IPv4 neighbor and there are no IPv4 neighbors in this setup, all the neighbors are IPv6-only. Best regards, Ilya Maximets.
On 5/30/24 20:17, Ilya Maximets wrote: > On 5/30/24 01:27, William Tu wrote: >> Add route-table support for ipv4 dst via ipv6. One use case is BGP >> unnumbered, a mechanism that establishes peering sessions without the >> need to explicitly configure IPv4 addresses on the interfaces involved >> in the peering. Without using IPv4 address assignments, it uses >> link-local IPv6 addresses of the directly connected neighbors for >> peering purposes. For example, BGP might install the following route: >> $ ip route get 100.87.18.3 >> 100.87.18.3 via inet6 fe80::920a:84ff:fe9e:9570 \ >> dev br-phy src 100.87.18.6 >> >> Note that the v6 addr fe80::920a:84ff:fe9e:9570 is not being used in >> the packet header, but only used for lookup the out dev br-phy. >> Currently OVS can only support either all-ipv4 or all-ipv6, the patch >> adds support for such use case. >> >> Reported-at: https://mail.openvswitch.org/pipermail/ovs-discuss/2024-January/052908.html >> Acked-by: Simon Horman <horms@ovn.org> >> Signed-off-by: William Tu <witu@nvidia.com> >> --- >> v5: fix minor CI failure >> v4: feedback from Ilya >> - add route del test case, wrap around test width >> - not set neighbor cache manually >> - on br-phy, use /32 on address in steead of /24 >> compare v3 and v4 >> https://github.com/williamtu/ovs/compare/router..router-v4 >> v3: add vxlan test, remove rfc >> v2: fix CI error >> --- > > <snip> > >> diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at >> index 508737c53ec6..7266f0990570 100644 >> --- a/tests/tunnel-push-pop.at >> +++ b/tests/tunnel-push-pop.at >> @@ -196,6 +196,69 @@ OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 100022eb0000000120000237 | wc -l` >> OVS_VSWITCHD_STOP >> AT_CLEANUP >> >> +AT_SETUP([tunnel_push_pop - v4 via v6 route]) >> + >> +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) >> +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) >> +AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=vxlan \ >> + options:remote_ip=1.1.2.92 options:key=123 ofport_request=1\ >> + ], [0]) >> + >> +AT_CHECK([ovs-appctl dpif/show], [0], [dnl >> +dummy@ovs-dummy: hit:0 missed:0 >> + br0: >> + br0 65534/100: (dummy-internal) >> + p0 1/1: (dummy) >> + int-br: >> + int-br 65534/2: (dummy-internal) >> + t1 1/4789: (vxlan: key=123, remote_ip=1.1.2.92) >> +]) >> + >> +AT_CHECK([ovs-ofctl add-flow br0 action=normal]) >> + >> +dnl Setup dummy interface IP addresses. >> +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/32], [0], [OK >> +]) >> +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/64], [0], [OK >> +]) >> +dnl Add a static v4 via v6 route >> +AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/32 br0 2001:cafe::10 src=1.1.2.89], [0], [OK >> +]) >> + >> +AT_CHECK([ovs-appctl ovs/route/show | grep br0 | sort], [0], [dnl >> +Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local >> +Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local >> +User: 1.1.2.92/32 dev br0 GW 2001:cafe::10 SRC 1.1.2.89 >> +]) >> + >> +dnl Check ARP Snoop >> +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(100),dnl >> +eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),dnl >> +arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)']) > > This is still not a correct test, we would never receive an ARP > from an IPv6-only network. This must be an IPv6 NA packet instead. > > All in all, I'd expect the following test to work without modifications > (unless I mistyped something): > > --- > AT_SETUP([tunnel_push_pop - v4 via v6 route]) > > OVS_VSWITCHD_START( > [add-port br0 p0 \ > -- set Interface p0 type=dummy ofport_request=1 \ > other-config:hwaddr=aa:55:aa:55:00:00]) > AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg]) > AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy]) > AT_CHECK([ovs-vsctl add-port int-br t2 \ > -- set Interface t2 type=geneve \ > options:remote_ip=1.1.2.92 \ > options:key=123 ofport_request=2]) > > dnl Setup IP addresses. > AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/32], [0], [OK > ]) > AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/64], [0], [OK > ]) > dnl Adding a static v4 via v6 route. > AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/32 br0 2001:cafe::10 src=1.1.2.88], [0], [OK > ]) > > dnl Checking that a local route for added IP was successfully installed. > AT_CHECK([ovs-appctl ovs/route/show | grep br0 | sort], [0], [dnl > Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local > Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local > User: 1.1.2.92/32 dev br0 GW 2001:cafe::10 SRC 1.1.2.88 > ]) > > AT_CHECK([ovs-ofctl add-flow br0 action=normal]) > AT_CHECK([ovs-ofctl add-flow int-br action=normal]) > > AT_CHECK([ovs-vsctl -- set Interface p0 options:tx_pcap=p0.pcap]) > > dnl Check that v4-over-v6 route is used in the trace and that a tunnel neighbor > dnl lookup miss generates ND and not an ARP. > AT_CHECK([ovs-appctl ofproto/trace int-br in_port=LOCAL \ > | grep -E 'tunnel|neighbor|actions'], [0], [dnl > -> output to native tunnel > -> tunneling to 2001:cafe::10 via br0 > -> neighbor cache miss for 2001:cafe::10 on bridge br0, sending ND request > Datapath actions: drop > ]) > > dnl Check that the correct Neighbor Solicitation was sent out via p0. > m4_define([ND_NS_PACKET], [m4_joinall([,], > [eth_src=aa:55:aa:55:00:00,eth_dst=33:33:ff:00:00:10,eth_type=0x86dd], > [ipv6_src=2001:cafe::88,ipv6_dst=ff02::1:ff00:10], > [nw_proto=58,nw_ttl=255,nw_frag=no], > [icmpv6_type=135,icmpv6_code=0], > [nd_target=2001:cafe::10,nd_options_type=1,nd_sll=aa:55:aa:55:00:00])]) > > OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap \ > | grep -c "$(ovs-ofctl compose-packet --bare 'ND_NS_PACKET')") -eq 1]) > > dnl Now send a Neighbor Advertisement from p0 which has two effects: > dnl 1. The neighbor cache will learn that 2001:cafe::10 is at f8:bc:12:44:34:b6. > dnl 2. The br0 mac learning will learn that f8:bc:12:44:34:b6 is on p0. > AT_CHECK([ovs-appctl netdev-dummy/receive p0 dnl > 'recirc_id(0),in_port(1),dnl > eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),dnl > ipv6(src=2001:cafe::10,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),dnl > icmpv6(type=136,code=0),dnl > nd(target=2001:cafe::10,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)' > ]) > > dnl Check that v4-over-v6 route is used in the trace and the tunnel is working. > AT_CHECK([ovs-appctl ofproto/trace int-br in_port=LOCAL \ > | grep -E 'tunnel|neighbor|actions'], [0], [dnl > -> output to native tunnel > -> tunneling to 2001:cafe::10 via br0 > -> tunneling from aa:55:aa:55:00:00 1.1.2.88 to f8:bc:12:44:34:b6 2001:cafe::10 Though, I think, we should make this output less confusing, e.g. -> tunneling from aa:55:aa:55:00:00 1.1.2.88 to 1.1.2.92 via f8:bc:12:44:34:b6 2001:cafe::10 Or something like that. Otherwise it's lacking the actual destination IP information and may be hard to understand. > Datapath actions: tnl_push(tnl_port(6081),header(size=50,type=5,dnl > eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),dnl > ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),dnl > udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100)),1 > ]) > > dnl Now check that the packet is actually encapsulated and delivered. > packet=50540000000a5054000000091234 > eth=f8bc124434b6aa55aa5500000800 > ip4=450000320000400040113406010102580101025c > dnl Source port is based on a packet hash, so it may differ depending on the > dnl compiler flags and CPU type. Masked with '....'. > udp=....17c1001e0000 > geneve=0000655800007b00 > encap=${eth}${ip4}${udp}${geneve} > dnl Output to the tunnel from the int-br internal port. > dnl Checking that the packet arrived and it was correctly encapsulated. > AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"]) > OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 1]) > > dnl Sending again to exercise the non-miss upcall path. > AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"]) > OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 2]) > > dnl Finally, checking that the datapath flow is also correct. > AT_CHECK([ovs-appctl dpctl/dump-flows | grep tnl_push \ > | strip_ufid | strip_used], [0], [dnl > recirc_id(0),in_port(2),packet_type(ns=0,id=0),dnl > eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234), dnl > packets:1, bytes:14, used:0.0s, dnl > actions:tnl_push(tnl_port(6081),header(size=50,type=5,dnl > eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),dnl > ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),dnl > udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100)),1 > ]) > > OVS_VSWITCHD_STOP > AT_CLEANUP > --- > > With the current version of a patch it fails on the tunnel neighbor > lookup because it looks for IPv4 neighbor and there are no IPv4 > neighbors in this setup, all the neighbors are IPv6-only. > > Best regards, Ilya Maximets.
Hi Ilya, thanks for your review! The patch passes my githug-ci https://github.com/williamtu/ovs/actions/runs/9293675528/job/25577358954 I don't know why it fails/skipped at https://github.com/ovsrobot/ovs/actions/runs/9294537471 On 5/30/24 11:17 AM, Ilya Maximets wrote: > <snip> > >> diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at >> index 508737c53ec6..7266f0990570 100644 >> --- a/tests/tunnel-push-pop.at >> +++ b/tests/tunnel-push-pop.at >> @@ -196,6 +196,69 @@ OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 100022eb0000000120000237 | wc -l` >> OVS_VSWITCHD_STOP >> AT_CLEANUP >> >> +AT_SETUP([tunnel_push_pop - v4 via v6 route]) >> + >> +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) >> +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) >> +AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=vxlan \ >> + options:remote_ip=1.1.2.92 options:key=123 ofport_request=1\ >> + ], [0]) >> + >> +AT_CHECK([ovs-appctl dpif/show], [0], [dnl >> +dummy@ovs-dummy: hit:0 missed:0 >> + br0: >> + br0 65534/100: (dummy-internal) >> + p0 1/1: (dummy) >> + int-br: >> + int-br 65534/2: (dummy-internal) >> + t1 1/4789: (vxlan: key=123, remote_ip=1.1.2.92) >> +]) >> + >> +AT_CHECK([ovs-ofctl add-flow br0 action=normal]) >> + >> +dnl Setup dummy interface IP addresses. >> +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/32], [0], [OK >> +]) >> +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/64], [0], [OK >> +]) >> +dnl Add a static v4 via v6 route >> +AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/32 br0 2001:cafe::10 src=1.1.2.89], [0], [OK >> +]) >> + >> +AT_CHECK([ovs-appctl ovs/route/show | grep br0 | sort], [0], [dnl >> +Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local >> +Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local >> +User: 1.1.2.92/32 dev br0 GW 2001:cafe::10 SRC 1.1.2.89 >> +]) >> + >> +dnl Check ARP Snoop >> +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(100),dnl >> +eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),dnl >> +arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)']) > This is still not a correct test, we would never receive an ARP > from an IPv6-only network. This must be an IPv6 NA packet instead. > > All in all, I'd expect the following test to work without modifications > (unless I mistyped something): thanks a lot, this is very clear! I applied your test and hit issue below > --- > AT_SETUP([tunnel_push_pop - v4 via v6 route]) > > OVS_VSWITCHD_START( > [add-port br0 p0 \ > -- set Interface p0 type=dummy ofport_request=1 \ > other-config:hwaddr=aa:55:aa:55:00:00]) > AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg]) > AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy]) > AT_CHECK([ovs-vsctl add-port int-br t2 \ > -- set Interface t2 type=geneve \ > options:remote_ip=1.1.2.92 \ > options:key=123 ofport_request=2]) > > dnl Setup IP addresses. > AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/32], [0], [OK > ]) > AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/64], [0], [OK > ]) > dnl Adding a static v4 via v6 route. > AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/32 br0 2001:cafe::10 src=1.1.2.88], [0], [OK > ]) > > dnl Checking that a local route for added IP was successfully installed. > AT_CHECK([ovs-appctl ovs/route/show | grep br0 | sort], [0], [dnl > Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local > Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local > User: 1.1.2.92/32 dev br0 GW 2001:cafe::10 SRC 1.1.2.88 > ]) > > AT_CHECK([ovs-ofctl add-flow br0 action=normal]) > AT_CHECK([ovs-ofctl add-flow int-br action=normal]) > > AT_CHECK([ovs-vsctl -- set Interface p0 options:tx_pcap=p0.pcap]) > > dnl Check that v4-over-v6 route is used in the trace and that a tunnel neighbor > dnl lookup miss generates ND and not an ARP. > AT_CHECK([ovs-appctl ofproto/trace int-br in_port=LOCAL \ > | grep -E 'tunnel|neighbor|actions'], [0], [dnl > -> output to native tunnel > -> tunneling to 2001:cafe::10 via br0 > -> neighbor cache miss for 2001:cafe::10 on bridge br0, sending ND request > Datapath actions: drop > ]) hitting an error here: so the native tunnel is looking for 1.1.2.92, not the ipv6 address +++ /root/ovs/tests/testsuite.dir/at-groups/815/stdout 2024-06-01 17:12:56.836000000 +0300 @@ -1,5 +1,5 @@ -> output to native tunnel - -> tunneling to 2001:cafe::10 via br0 - -> neighbor cache miss for 2001:cafe::10 on bridge br0, sending ND request + -> tunneling to 1.1.2.92 via br0 + -> neighbor cache miss for 1.1.2.92 on bridge br0, sending ARP request Datapath actions: drop I think I still need to change some code in native tunnel... here although "remote_ip" is 1.1.2.92, but we want to change it to 2001:cafe::10? > > dnl Check that the correct Neighbor Solicitation was sent out via p0. > m4_define([ND_NS_PACKET], [m4_joinall([,], > [eth_src=aa:55:aa:55:00:00,eth_dst=33:33:ff:00:00:10,eth_type=0x86dd], > [ipv6_src=2001:cafe::88,ipv6_dst=ff02::1:ff00:10], > [nw_proto=58,nw_ttl=255,nw_frag=no], > [icmpv6_type=135,icmpv6_code=0], > [nd_target=2001:cafe::10,nd_options_type=1,nd_sll=aa:55:aa:55:00:00])]) > > OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap \ > | grep -c "$(ovs-ofctl compose-packet --bare 'ND_NS_PACKET')") -eq 1]) > > dnl Now send a Neighbor Advertisement from p0 which has two effects: > dnl 1. The neighbor cache will learn that 2001:cafe::10 is at f8:bc:12:44:34:b6. but in the end, it's ipv4 1.1.2.92 > dnl 2. The br0 mac learning will learn that f8:bc:12:44:34:b6 is on p0. > AT_CHECK([ovs-appctl netdev-dummy/receive p0 dnl > 'recirc_id(0),in_port(1),dnl > eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),dnl > ipv6(src=2001:cafe::10,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),dnl > icmpv6(type=136,code=0),dnl > nd(target=2001:cafe::10,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)' > ]) > > dnl Check that v4-over-v6 route is used in the trace and the tunnel is working. > AT_CHECK([ovs-appctl ofproto/trace int-br in_port=LOCAL \ > | grep -E 'tunnel|neighbor|actions'], [0], [dnl > -> output to native tunnel > -> tunneling to 2001:cafe::10 via br0 > -> tunneling from aa:55:aa:55:00:00 1.1.2.88 to f8:bc:12:44:34:b6 2001:cafe::10 > Datapath actions: tnl_push(tnl_port(6081),header(size=50,type=5,dnl > eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),dnl > ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),dnl > udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100)),1 > ]) So here we want to tunneling to 2001:cafe::10, but when push the header, we want to push ipv4. Let me think through again... Thanks William > > dnl Now check that the packet is actually encapsulated and delivered. > packet=50540000000a5054000000091234 > eth=f8bc124434b6aa55aa5500000800 > ip4=450000320000400040113406010102580101025c > dnl Source port is based on a packet hash, so it may differ depending on the > dnl compiler flags and CPU type. Masked with '....'. > udp=....17c1001e0000 > geneve=0000655800007b00 > encap=${eth}${ip4}${udp}${geneve} > dnl Output to the tunnel from the int-br internal port. > dnl Checking that the packet arrived and it was correctly encapsulated. > AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"]) > OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 1]) > > dnl Sending again to exercise the non-miss upcall path. > AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}"]) > OVS_WAIT_UNTIL([test $(ovs-pcap p0.pcap | grep -c "${encap}${packet}") -eq 2]) > > dnl Finally, checking that the datapath flow is also correct. > AT_CHECK([ovs-appctl dpctl/dump-flows | grep tnl_push \ > | strip_ufid | strip_used], [0], [dnl > recirc_id(0),in_port(2),packet_type(ns=0,id=0),dnl > eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x1234), dnl > packets:1, bytes:14, used:0.0s, dnl > actions:tnl_push(tnl_port(6081),header(size=50,type=5,dnl > eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),dnl > ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),dnl > udp(src=0,dst=6081,csum=0x0),geneve(vni=0x7b)),out_port(100)),1 > ]) > > OVS_VSWITCHD_STOP > AT_CLEANUP > --- > > With the current version of a patch it fails on the tunnel neighbor > lookup because it looks for IPv4 neighbor and there are no IPv4 > neighbors in this setup, all the neighbors are IPv6-only. > > Best regards, Ilya Maximets.
diff --git a/lib/ovs-router.c b/lib/ovs-router.c index 3d84c9a30a8f..fbf67b666993 100644 --- a/lib/ovs-router.c +++ b/lib/ovs-router.c @@ -184,6 +184,11 @@ verify_prefsrc(const struct in6_addr *ip6_dst, goto out; } + /* Skip the check if not the same address family */ + if (!IN6_IS_ADDR_V4MAPPED(ip6_dst) && IN6_IS_ADDR_V4MAPPED(prefsrc)) { + goto out; + } + for (i = 0; i < n_in6; i++) { struct in6_addr a1, a2; a1 = ipv6_addr_bitand(ip6_dst, &mask[i]); @@ -415,7 +420,6 @@ ovs_router_add(struct unixctl_conn *conn, int argc, unsigned int plen; ovs_be32 src = 0; ovs_be32 gw = 0; - bool is_ipv6; ovs_be32 ip; int err; int i; @@ -423,9 +427,8 @@ ovs_router_add(struct unixctl_conn *conn, int argc, if (scan_ipv4_route(argv[1], &ip, &plen)) { in6_addr_set_mapped_ipv4(&ip6, ip); plen += 96; - is_ipv6 = false; } else if (scan_ipv6_route(argv[1], &ip6, &plen)) { - is_ipv6 = true; + ; } else { unixctl_command_reply_error(conn, "Invalid 'ip/plen' parameter"); @@ -438,21 +441,21 @@ ovs_router_add(struct unixctl_conn *conn, int argc, continue; } - if (is_ipv6) { - if (ovs_scan(argv[i], "src="IPV6_SCAN_FMT, src6_s) && - ipv6_parse(src6_s, &src6)) { - continue; - } - if (ipv6_parse(argv[i], &gw6)) { - continue; - } - } else { - if (ovs_scan(argv[i], "src="IP_SCAN_FMT, IP_SCAN_ARGS(&src))) { - continue; - } - if (ip_parse(argv[i], &gw)) { - continue; - } + if (ovs_scan(argv[i], "src="IPV6_SCAN_FMT, src6_s) && + ipv6_parse(src6_s, &src6)) { + continue; + } + + if (ipv6_parse(argv[i], &gw6)) { + continue; + } + + if (ovs_scan(argv[i], "src="IP_SCAN_FMT, IP_SCAN_ARGS(&src))) { + continue; + } + + if (ip_parse(argv[i], &gw)) { + continue; } unixctl_command_reply_error(conn, diff --git a/lib/route-table.c b/lib/route-table.c index f1fe32714e8d..58412711888f 100644 --- a/lib/route-table.c +++ b/lib/route-table.c @@ -232,6 +232,7 @@ route_table_parse(struct ofpbuf *buf, struct route_table_msg *change) [RTA_OIF] = { .type = NL_A_U32, .optional = true }, [RTA_GATEWAY] = { .type = NL_A_U32, .optional = true }, [RTA_MARK] = { .type = NL_A_U32, .optional = true }, + [RTA_VIA] = { .type = NL_A_UNSPEC, .optional = true }, [RTA_PREFSRC] = { .type = NL_A_U32, .optional = true }, [RTA_TABLE] = { .type = NL_A_U32, .optional = true }, }; @@ -241,6 +242,7 @@ route_table_parse(struct ofpbuf *buf, struct route_table_msg *change) [RTA_OIF] = { .type = NL_A_U32, .optional = true }, [RTA_MARK] = { .type = NL_A_U32, .optional = true }, [RTA_GATEWAY] = { .type = NL_A_IPV6, .optional = true }, + [RTA_VIA] = { .type = NL_A_UNSPEC, .optional = true }, [RTA_PREFSRC] = { .type = NL_A_IPV6, .optional = true }, [RTA_TABLE] = { .type = NL_A_U32, .optional = true }, }; @@ -333,6 +335,25 @@ route_table_parse(struct ofpbuf *buf, struct route_table_msg *change) nl_attr_get_in6_addr(attrs[RTA_PREFSRC]); } } + if (attrs[RTA_VIA]) { + const struct rtvia *via; + ovs_be32 gw; + + via = nl_attr_get(attrs[RTA_VIA]); + switch (via->rtvia_family) { + case AF_INET: + gw = *(ALIGNED_CAST(ovs_be32 *, via->rtvia_addr)); + in6_addr_set_mapped_ipv4(&change->rd.rta_gw, gw); + break; + case AF_INET6: + change->rd.rta_gw = *(ALIGNED_CAST(struct in6_addr *, + via->rtvia_addr)); + break; + default: + VLOG_WARN("Unknown address family %d\n", via->rtvia_family); + return 0; + } + } if (attrs[RTA_GATEWAY]) { if (ipv4) { ovs_be32 gw; diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 7c495089509f..3694a8430382 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -3612,7 +3612,8 @@ tnl_route_lookup_flow(const struct xlate_ctx *ctx, } if (ipv6_addr_is_set(&gw) && - (!IN6_IS_ADDR_V4MAPPED(&gw) || in6_addr_get_mapped_ipv4(&gw))) { + (!IN6_IS_ADDR_V4MAPPED(&gw) || in6_addr_get_mapped_ipv4(&gw)) && + (!IN6_IS_ADDR_V4MAPPED(&dst) || IN6_IS_ADDR_V4MAPPED(&gw))) { *ip = gw; } else { *ip = dst; diff --git a/tests/ovs-router.at b/tests/ovs-router.at index b3314b3dff0d..5e5e1d013464 100644 --- a/tests/ovs-router.at +++ b/tests/ovs-router.at @@ -109,6 +109,57 @@ User: 2001:db8:beef::14/128 MARK 14 dev br0 GW 2001:db8:cafe::1 SRC 2001:db8:caf OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([appctl - route/add and del with ipv4 via ipv6]) +AT_KEYWORDS([ovs_router]) +OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy]) +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 192.168.9.2/24], [0], [OK +]) +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 192.168.9.3/24], [0], [OK +]) + +dnl defualt pick the first IP, 192.168.9.2, as src +AT_CHECK([ovs-appctl ovs/route/add 192.168.9.10/32 br0 dnl +fe80::920a:84ff:beef:9510], [0], [OK +]) +AT_CHECK([ovs-appctl ovs/route/add 192.168.9.11/32 br0 dnl +fe80::920a:84ff:beef:9511 src=192.168.9.2], [0], [OK +]) +AT_CHECK([ovs-appctl ovs/route/add 192.168.9.12/32 br0 dnl +fe80::920a:84ff:beef:9512 src=192.168.9.3], [0], [OK +]) +AT_CHECK([ovs-appctl ovs/route/add 192.168.9.13/32 br0 dnl +fe80::920a:84ff:beef:9513 pkt_mark=13 src=192.168.9.3], [0], [OK +]) + +AT_CHECK([ovs-appctl ovs/route/show | grep User | grep beef | sort], [0], [dnl +User: 192.168.9.10/32 dev br0 GW fe80::920a:84ff:beef:9510 SRC 192.168.9.2 +User: 192.168.9.11/32 dev br0 GW fe80::920a:84ff:beef:9511 SRC 192.168.9.2 +User: 192.168.9.12/32 dev br0 GW fe80::920a:84ff:beef:9512 SRC 192.168.9.3 +User: 192.168.9.13/32 MARK 13 dev br0 GW fe80::920a:84ff:beef:9513 SRC 192.168.9.3 +]) + +dnl DST and SRC can be in different domain +AT_CHECK([ovs-appctl ovs/route/add 192.168.10.12/32 br0 dnl +fe80::920a:84ff:face:9512 src=192.168.9.3], [0], [OK +]) +AT_CHECK([ovs-appctl ovs/route/show | grep User | grep face | sort], [0], [dnl +User: 192.168.10.12/32 dev br0 GW fe80::920a:84ff:face:9512 SRC 192.168.9.3 +]) + +dnl Delete route +AT_CHECK([ovs-appctl ovs/route/del 192.168.9.10/32], [0], [OK +]) +AT_CHECK([ovs-appctl ovs/route/del 192.168.9.11/32], [0], [OK +]) +AT_CHECK([ovs-appctl ovs/route/del 192.168.9.12/32], [0], [OK +]) +AT_CHECK([ovs-appctl ovs/route/del 192.168.9.13/32 pkt_mark=13], [0], [OK +]) +OVS_WAIT_UNTIL([test $(ovs-appctl ovs/route/show | grep -c '192.168.9.1') -eq 0 ]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([appctl - route/lookup]) AT_KEYWORDS([ovs_router]) OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=dummy]) diff --git a/tests/system-route.at b/tests/system-route.at index c0ecad6cfb49..dbb2afa5a8fe 100644 --- a/tests/system-route.at +++ b/tests/system-route.at @@ -65,6 +65,45 @@ Cached: fc00:db8:beef::13/128 dev br0 GW fc00:db8:cafe::1 SRC fc00:db8:cafe::2]) OVS_TRAFFIC_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([ovs-route - add and del system route ipv4 via ipv6]) +AT_KEYWORDS([route]) +OVS_TRAFFIC_VSWITCHD_START() +AT_CHECK([ip link set br0 up]) + +AT_CHECK([ip addr add 192.168.9.2/24 dev br0], [0], [stdout]) +AT_CHECK([ip addr add 192.168.9.3/24 dev br0], [0], [stdout]) + +AT_CHECK([ip -6 addr add fc00:db8:cafe::2/64 dev br0], [0], [stdout]) +AT_CHECK([ip -6 addr add fc00:db8:cafe::3/64 dev br0], [0], [stdout]) + +AT_CHECK([ip route add 192.168.9.12/32 dev br0 dnl +via inet6 fe80::920a:84ff:fe9e:9512 src 192.168.9.2], [0], [stdout]) +AT_CHECK([ip route add 192.168.9.13/32 dev br0 dnl +via inet6 fe80::920a:84ff:fe9e:9513 src 192.168.9.3], [0], [stdout]) + +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E '192.168.9.1[[23]]/32' | sort], [dnl +Cached: 192.168.9.12/32 dev br0 GW fe80::920a:84ff:fe9e:9512 SRC 192.168.9.2 +Cached: 192.168.9.13/32 dev br0 GW fe80::920a:84ff:fe9e:9513 SRC 192.168.9.3]) + +AT_CHECK([ovs-appctl ovs/route/add 192.168.9.14/32 br0 dnl +fe80::920a:84ff:fe9e:9514 src=192.168.9.2], [0], [OK +]) + +OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E '192.168.9.14/32' | sort], [dnl +User: 192.168.9.14/32 dev br0 GW fe80::920a:84ff:fe9e:9514 SRC 192.168.9.2]) + +dnl Delete system cached route +AT_CHECK([ip route del 192.168.9.12/32 dev br0 dnl +via inet6 fe80::920a:84ff:fe9e:9512 src 192.168.9.2], [0], [stdout]) +AT_CHECK([ip route del 192.168.9.13/32 dev br0 dnl +via inet6 fe80::920a:84ff:fe9e:9513 src 192.168.9.3], [0], [stdout]) + +OVS_WAIT_UNTIL([test $(ovs-appctl ovs/route/show | grep -c '192.168.9.12/32') -eq 0 ]) +OVS_WAIT_UNTIL([test $(ovs-appctl ovs/route/show | grep -c '192.168.9.13/32') -eq 0 ]) + +OVS_TRAFFIC_VSWITCHD_STOP +AT_CLEANUP + dnl Checks that OVS doesn't use routes from non-standard tables. AT_SETUP([ovs-route - route tables]) AT_KEYWORDS([route]) diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at index 508737c53ec6..7266f0990570 100644 --- a/tests/tunnel-push-pop.at +++ b/tests/tunnel-push-pop.at @@ -196,6 +196,69 @@ OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 100022eb0000000120000237 | wc -l` OVS_VSWITCHD_STOP AT_CLEANUP +AT_SETUP([tunnel_push_pop - v4 via v6 route]) + +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00]) +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0]) +AT_CHECK([ovs-vsctl add-port int-br t1 -- set Interface t1 type=vxlan \ + options:remote_ip=1.1.2.92 options:key=123 ofport_request=1\ + ], [0]) + +AT_CHECK([ovs-appctl dpif/show], [0], [dnl +dummy@ovs-dummy: hit:0 missed:0 + br0: + br0 65534/100: (dummy-internal) + p0 1/1: (dummy) + int-br: + int-br 65534/2: (dummy-internal) + t1 1/4789: (vxlan: key=123, remote_ip=1.1.2.92) +]) + +AT_CHECK([ovs-ofctl add-flow br0 action=normal]) + +dnl Setup dummy interface IP addresses. +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/32], [0], [OK +]) +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/64], [0], [OK +]) +dnl Add a static v4 via v6 route +AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/32 br0 2001:cafe::10 src=1.1.2.89], [0], [OK +]) + +AT_CHECK([ovs-appctl ovs/route/show | grep br0 | sort], [0], [dnl +Cached: 1.1.2.88/32 dev br0 SRC 1.1.2.88 local +Cached: 2001:cafe::/64 dev br0 SRC 2001:cafe::88 local +User: 1.1.2.92/32 dev br0 GW 2001:cafe::10 SRC 1.1.2.89 +]) + +dnl Check ARP Snoop +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'recirc_id(0),in_port(100),dnl +eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),dnl +arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)']) + +ovs-appctl time/warp 1000 +ovs-appctl time/warp 1000 + +AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl +1.1.2.92 f8:bc:12:44:34:b6 br0 +]) + +dnl Check VXLAN tunnel push +AT_CHECK([ovs-ofctl add-flow int-br action=1]) +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),dnl +eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x0800),dnl +ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout]) + +AT_CHECK([tail -1 stdout], [0], + [Datapath actions: tnl_push(tnl_port(4789),header(size=50,type=4,dnl +eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),dnl +ipv4(src=1.1.2.89,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),dnl +udp(src=0,dst=4789,csum=0x0),vxlan(flags=0x8000000,vni=0x7b)),out_port(100)),1 +]) + +OVS_VSWITCHD_STOP +AT_CLEANUP + AT_SETUP([tunnel_push_pop - action]) OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])