Skip to content

Commit f17b6ce

Browse files
gabrieleceraminumansiddique
authored andcommitted
Honour router_preference for solicited RA
Replies to router solicitation follow a different flow than periodic RA. This flow currently does not honour the router_preference configuration. This patch modifies the flow to honour the flag, and send router-preference indications in the reply RA following RFC4191 specifications Reported-at: https://bugzilla.redhat.com/show_bug.cgi?id=1804576 Signed-off-by: Gabriele Cerami <[email protected]> Signed-off-by: Numan Siddique <[email protected]>
1 parent f50a037 commit f17b6ce

File tree

5 files changed

+55
-12
lines changed

5 files changed

+55
-12
lines changed

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ Frédéric Tobias Christ [email protected]
147147
Frode Nordahl [email protected]
148148
FUJITA Tomonori [email protected]
149149
Gabe Beged-Dov [email protected]
150+
Gabriele Cerami [email protected]
150151
Gaetano Catalli [email protected]
151152
152153
Genevieve LEsperance [email protected]

lib/actions.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,12 @@ parse_put_nd_ra_opts(struct action_context *ctx, const struct expr_field *dst,
25472547
}
25482548
break;
25492549

2550+
case ND_RA_FLAG_PRF:
2551+
ok = (c->string && (!strcmp(c->string, "MEDIUM") ||
2552+
!strcmp(c->string, "HIGH") ||
2553+
!strcmp(c->string, "LOW")));
2554+
break;
2555+
25502556
case ND_OPT_SOURCE_LINKADDR:
25512557
ok = c->format == LEX_F_ETHERNET;
25522558
slla_present = true;
@@ -2601,9 +2607,22 @@ encode_put_nd_ra_option(const struct ovnact_gen_option *o,
26012607
{
26022608
struct ovs_ra_msg *ra = ofpbuf_at(ofpacts, ra_offset, sizeof *ra);
26032609
if (!strcmp(c->string, "dhcpv6_stateful")) {
2604-
ra->mo_flags = IPV6_ND_RA_FLAG_MANAGED_ADDR_CONFIG;
2610+
ra->mo_flags |= IPV6_ND_RA_FLAG_MANAGED_ADDR_CONFIG;
26052611
} else if (!strcmp(c->string, "dhcpv6_stateless")) {
2606-
ra->mo_flags = IPV6_ND_RA_FLAG_OTHER_ADDR_CONFIG;
2612+
ra->mo_flags |= IPV6_ND_RA_FLAG_OTHER_ADDR_CONFIG;
2613+
}
2614+
break;
2615+
}
2616+
2617+
case ND_RA_FLAG_PRF:
2618+
{
2619+
struct ovs_ra_msg *ra = ofpbuf_at(ofpacts, ra_offset, sizeof *ra);
2620+
if (!strcmp(c->string, "LOW")) {
2621+
ra->mo_flags |= IPV6_ND_RA_OPT_PRF_LOW;
2622+
} else if (!strcmp(c->string, "HIGH")) {
2623+
ra->mo_flags |= IPV6_ND_RA_OPT_PRF_HIGH;
2624+
} else {
2625+
ra->mo_flags |= IPV6_ND_RA_OPT_PRF_NORMAL;
26072626
}
26082627
break;
26092628
}
@@ -2684,6 +2703,12 @@ encode_PUT_ND_RA_OPTS(const struct ovnact_put_opts *po,
26842703
encode_put_nd_ra_option(o, ofpacts, ra_offset);
26852704
}
26862705

2706+
/* RFC4191 section 2.2 */
2707+
struct ovs_ra_msg *new_ra = ofpbuf_at(ofpacts, ra_offset, sizeof *new_ra);
2708+
if (ntohs(new_ra->router_lifetime) == 0) {
2709+
new_ra->mo_flags &= IPV6_ND_RA_OPT_PRF_RESET_MASK;
2710+
}
2711+
26872712
encode_finish_controller_op(oc_offset, ofpacts);
26882713
}
26892714

lib/ovn-l7.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ nd_ra_opts_destroy(struct hmap *nd_ra_opts)
309309

310310

311311
#define ND_RA_FLAG_ADDR_MODE 0
312+
/* all small numbers seems to be all already taken but nothing guarantees this
313+
* code will not be assigned by IANA to another option */
314+
#define ND_RA_FLAG_PRF 255
312315

313316

314317
/* Default values of various IPv6 Neighbor Discovery protocol options and
@@ -330,11 +333,13 @@ nd_ra_opts_destroy(struct hmap *nd_ra_opts)
330333
#define IPV6_ND_RA_OPT_PRF_NORMAL 0x00
331334
#define IPV6_ND_RA_OPT_PRF_HIGH 0x08
332335
#define IPV6_ND_RA_OPT_PRF_LOW 0x18
336+
#define IPV6_ND_RA_OPT_PRF_RESET_MASK 0xe7
333337

334338
static inline void
335339
nd_ra_opts_init(struct hmap *nd_ra_opts)
336340
{
337341
nd_ra_opt_add(nd_ra_opts, "addr_mode", ND_RA_FLAG_ADDR_MODE, "str");
342+
nd_ra_opt_add(nd_ra_opts, "router_preference", ND_RA_FLAG_PRF, "str");
338343
nd_ra_opt_add(nd_ra_opts, "slla", ND_OPT_SOURCE_LINKADDR, "mac");
339344
nd_ra_opt_add(nd_ra_opts, "prefix", ND_OPT_PREFIX_INFORMATION, "ipv6");
340345
nd_ra_opt_add(nd_ra_opts, "mtu", ND_OPT_MTU, "uint32");

northd/ovn-northd.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9455,6 +9455,12 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
94559455
ds_put_format(&actions, ", mtu = %u", mtu);
94569456
}
94579457

9458+
const char *prf = smap_get_def(
9459+
&op->nbrp->ipv6_ra_configs, "router_preference", "MEDIUM");
9460+
if (strcmp(prf, "MEDIUM")) {
9461+
ds_put_format(&actions, ", router_preference = \"%s\"", prf);
9462+
}
9463+
94589464
bool add_rs_response_flow = false;
94599465

94609466
for (size_t i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {

tests/ovn.at

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,14 +1385,14 @@ log(severity=notice);
13851385
Syntax error at `;' expecting verdict.
13861386

13871387
# put_nd_ra_opts
1388-
reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::/64, slla = ae:01:02:03:04:05);
1389-
encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.00.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.dc.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.05,pause)
1388+
reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, router_preference = "HIGH", prefix = aef0::/64, slla = ae:01:02:03:04:05);
1389+
encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.08.ff.ff.00.00.00.00.00.00.00.00.05.01.00.00.00.00.05.dc.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.05,pause)
13901390
has prereqs ip6
1391-
reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", slla = ae:01:02:03:04:10, mtu = 1450);
1391+
reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateful", router_preference = "MEDIUM", slla = ae:01:02:03:04:10, mtu = 1450);
13921392
encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.80.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.10.05.01.00.00.00.00.05.aa,pause)
13931393
has prereqs ip6
1394-
reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", slla = ae:01:02:03:04:06, prefix = aef0::/64);
1395-
encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.40.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause)
1394+
reg1[0] = put_nd_ra_opts(addr_mode = "dhcpv6_stateless", router_preference = "LOW", slla = ae:01:02:03:04:06, prefix = aef0::/64);
1395+
encodes as controller(userdata=00.00.00.08.00.00.00.00.00.01.de.10.00.00.00.40.86.00.00.00.ff.58.ff.ff.00.00.00.00.00.00.00.00.01.01.ae.01.02.03.04.06.03.04.40.c0.ff.ff.ff.ff.ff.ff.ff.ff.00.00.00.00.ae.f0.00.00.00.00.00.00.00.00.00.00.00.00.00.00,pause)
13961396
has prereqs ip6
13971397
reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 1500, prefix = aef0::/64);
13981398
slla option not present
@@ -10734,13 +10734,16 @@ reset_pcap_file hv1-vif1 hv1/vif1
1073410734
reset_pcap_file hv1-vif2 hv1/vif2
1073510735
reset_pcap_file hv1-vif3 hv1/vif3
1073610736

10737-
# Set the MTU to 1500
10737+
# Set the MTU to 1500, send_periodic to false, preference to LOW
1073810738
ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:mtu=1500
10739+
ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:send_periodic="false"
10740+
ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:router_preference="LOW"
1073910741

1074010742
# Make sure that ovn-controller has installed the corresponding OF Flow.
1074110743
OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
1074210744

10743-
addr_mode=00
10745+
# addr_mode byte also includes router preference information
10746+
addr_mode=18
1074410747
default_prefix_option_config=030440c0ffffffffffffffff00000000
1074510748
src_mac=fa163e000003
1074610749
src_lla=fe80000000000000f8163efffe000003
@@ -10765,12 +10768,14 @@ reset_pcap_file hv1-vif1 hv1/vif1
1076510768
reset_pcap_file hv1-vif2 hv1/vif2
1076610769
reset_pcap_file hv1-vif3 hv1/vif3
1076710770

10768-
# Set the address mode to dhcpv6_stateful
10771+
# Set the address mode to dhcpv6_stateful, router_preference to HIGH
1076910772
ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=dhcpv6_stateful
10773+
ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:router_preference="HIGH"
1077010774
# Make sure that ovn-controller has installed the corresponding OF Flow.
1077110775
OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
1077210776

10773-
addr_mode=80
10777+
# addr_mode byte also includes router preference information
10778+
addr_mode=88
1077410779
default_prefix_option_config=03044080ffffffffffffffff00000000
1077510780
src_mac=fa163e000004
1077610781
src_lla=fe80000000000000f8163efffe000004
@@ -10795,8 +10800,9 @@ reset_pcap_file hv1-vif1 hv1/vif1
1079510800
reset_pcap_file hv1-vif2 hv1/vif2
1079610801
reset_pcap_file hv1-vif3 hv1/vif3
1079710802

10798-
# Set the address mode to dhcpv6_stateless
10803+
# Set the address mode to dhcpv6_stateless, reset router preference to default
1079910804
ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:address_mode=dhcpv6_stateless
10805+
ovn-nbctl --wait=hv set Logical_Router_Port lrp0 ipv6_ra_configs:router_preference="MEDIUM"
1080010806
# Make sure that ovn-controller has installed the corresponding OF Flow.
1080110807
OVS_WAIT_UNTIL([test 1 = `as hv1 ovs-ofctl dump-flows br-int | grep -c "ipv6_dst=ff02::2,nw_ttl=255,icmp_type=133,icmp_code=0"`])
1080210808

0 commit comments

Comments
 (0)