@@ -1852,7 +1852,7 @@ build_dhcpv4_action(struct ovn_port *op, ovs_be32 offer_ip,
}
static bool
-build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip,
+build_dhcpv6_action(struct ovn_port *op, struct lport_addresses *offer_ips,
struct ds *options_action, struct ds *response_action)
{
if (!op->nbsp->dhcpv6_options) {
@@ -1868,11 +1868,20 @@ build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip,
free(error);
return false;
}
- struct in6_addr ip6_mask = ipv6_addr_bitxor(offer_ip, &host_ip);
- ip6_mask = ipv6_addr_bitand(&ip6_mask, &mask);
- if (!ipv6_mask_is_any(&ip6_mask)) {
- /* offer_ip doesn't belongs to the cidr defined in lport's DHCPv6
- * options.*/
+
+ bool dhcpv6_option_match = false;
+ for (size_t i = 0; i != offer_ips->n_ipv6_addrs; i++) {
+ struct in6_addr ip6_mask = ipv6_addr_bitxor(
+ &offer_ips->ipv6_addrs[i].addr, &host_ip);
+ ip6_mask = ipv6_addr_bitand(&ip6_mask, &mask);
+ if (ipv6_mask_is_any(&ip6_mask)) {
+ dhcpv6_option_match = true;
+ break;
+ }
+ }
+ if (!dhcpv6_option_match) {
+ /* None of lswitch port ipv6 addresses belongs to the cidr defined in
+ * lswitch port's DHCPv6 options.*/
return false;
}
@@ -1896,11 +1905,12 @@ build_dhcpv6_action(struct ovn_port *op, struct in6_addr *offer_ip,
ipv6_string_mapped(server_ip, &lla);
char ia_addr[INET6_ADDRSTRLEN + 1];
- ipv6_string_mapped(ia_addr, offer_ip);
+ ds_put_cstr(options_action, REGBIT_DHCP_OPTS_RESULT" = put_dhcpv6_opts(");
+ for (size_t i = 0; i != offer_ips->n_ipv6_addrs; i++) {
+ ipv6_string_mapped(ia_addr, &offer_ips->ipv6_addrs[i].addr);
+ ds_put_format(options_action, "ia_addr = %s, ", ia_addr);
+ }
- ds_put_format(options_action,
- REGBIT_DHCP_OPTS_RESULT" = put_dhcpv6_opts(ia_addr = %s, ",
- ia_addr);
struct smap_node *node;
SMAP_FOR_EACH (node, &op->nbsp->dhcpv6_options->options) {
ds_put_format(options_action, "%s = %s, ", node->key, node->value);
@@ -2700,33 +2710,30 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
}
}
- for (size_t j = 0; j < op->lsp_addrs[i].n_ipv6_addrs; j++) {
- struct ds options_action = DS_EMPTY_INITIALIZER;
- struct ds response_action = DS_EMPTY_INITIALIZER;
- if (build_dhcpv6_action(
- op, &op->lsp_addrs[i].ipv6_addrs[j].addr,
- &options_action, &response_action)) {
- struct ds match = DS_EMPTY_INITIALIZER;
- ds_put_format(
- &match, "inport == %s && eth.src == %s"
- " && ip6.dst == ff02::1:2 && udp.src == 546 &&"
- " udp.dst == 547", op->json_key,
- op->lsp_addrs[i].ea_s);
-
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 100,
- ds_cstr(&match), ds_cstr(&options_action));
-
- /* If REGBIT_DHCP_OPTS_RESULT is set to 1, it means the
- * put_dhcpv6_opts action is successful */
- ds_put_cstr(&match, " && "REGBIT_DHCP_OPTS_RESULT);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE, 100,
- ds_cstr(&match), ds_cstr(&response_action));
- ds_destroy(&match);
- ds_destroy(&options_action);
- ds_destroy(&response_action);
- break;
- }
+ struct ds options_action = DS_EMPTY_INITIALIZER;
+ struct ds response_action = DS_EMPTY_INITIALIZER;
+ if (build_dhcpv6_action(
+ op, &op->lsp_addrs[i],
+ &options_action, &response_action)) {
+ struct ds match = DS_EMPTY_INITIALIZER;
+ ds_put_format(
+ &match, "inport == %s && eth.src == %s"
+ " && ip6.dst == ff02::1:2 && udp.src == 546 &&"
+ " udp.dst == 547", op->json_key,
+ op->lsp_addrs[i].ea_s);
+
+ ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 100,
+ ds_cstr(&match), ds_cstr(&options_action));
+
+ /* If REGBIT_DHCP_OPTS_RESULT is set to 1, it means the
+ * put_dhcpv6_opts action is successful */
+ ds_put_cstr(&match, " && "REGBIT_DHCP_OPTS_RESULT);
+ ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE, 100,
+ ds_cstr(&match), ds_cstr(&response_action));
+ ds_destroy(&match);
}
+ ds_destroy(&options_action);
+ ds_destroy(&response_action);
}
}