Re: [ovs-dev] [PATCH v5] route-table: Add support for v4 via v6 route.
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: 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 100022eb00012237 | 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.83600 +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([,],
Re: [ovs-dev] [PATCH v5] route-table: Add support for v4 via v6 route.
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 >> Signed-off-by: William Tu >> --- >> 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 >> --- > > > >> 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 >> 100022eb00012237 | 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]) > >
Re: [ovs-dev] [PATCH v5] route-table: Add support for v4 via v6 route.
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 > Signed-off-by: William Tu > --- > 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 > --- > 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 > 100022eb00012237 | 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
[ovs-dev] [PATCH v5] route-table: Add support for v4 via v6 route.
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 Signed-off-by: William Tu --- 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 --- lib/ovs-router.c | 39 +++--- lib/route-table.c| 21 ofproto/ofproto-dpif-xlate.c | 3 +- tests/ovs-router.at | 51 + tests/system-route.at| 39 ++ tests/tunnel-push-pop.at | 63 6 files changed, 197 insertions(+), 19 deletions(-) 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, [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], , )) { in6_addr_set_mapped_ipv4(, ip); plen += 96; -is_ipv6 = false; } else if (scan_ipv6_route(argv[1], , )) { -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, )) { -continue; -} -if (ipv6_parse(argv[i], )) { -continue; -} -} else { -if (ovs_scan(argv[i], "src="IP_SCAN_FMT, IP_SCAN_ARGS())) { -continue; -} -if (ip_parse(argv[i], )) { -continue; -} +if (ovs_scan(argv[i], "src="IPV6_SCAN_FMT, src6_s) && +ipv6_parse(src6_s, )) { +continue; +} + +if (ipv6_parse(argv[i], )) { +continue; +} + +if (ovs_scan(argv[i], "src="IP_SCAN_FMT, IP_SCAN_ARGS())) { +continue; +} + +if (ip_parse(argv[i], )) { +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]);