Message ID | 1591815613-49682-5-git-send-email-hzhou@ovn.org |
---|---|
State | Superseded |
Headers | show |
Series | Avoid ARP flow explosion. | expand |
On Thu, Jun 11, 2020 at 12:31 AM Han Zhou <hzhou@ovn.org> wrote: > lookup_arp_ip and lookup_nd_ip are added to lookup if an entry exists > in MAC bindings for a given IP address, for IPv4 and IPv6 respectively. > > Signed-off-by: Han Zhou <hzhou@ovn.org> > Hi Han, I know this is RFC. I was just going through it and noticed that this patch needs to document the new actions in ovn-sb.xml. Thanks Numan --- > controller/lflow.c | 4 +- > include/ovn/actions.h | 10 +++++ > lib/actions.c | 112 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > tests/ovn.at | 50 ++++++++++++++++++++++ > utilities/ovn-trace.c | 54 ++++++++++++++++++++++-- > 5 files changed, 226 insertions(+), 4 deletions(-) > > diff --git a/controller/lflow.c b/controller/lflow.c > index 01214a3..e45ed33 100644 > --- a/controller/lflow.c > +++ b/controller/lflow.c > @@ -761,13 +761,15 @@ consider_neighbor_flow(struct ovsdb_idl_index > *sbrec_port_binding_by_name, > > uint64_t stub[1024 / 8]; > struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub); > + uint8_t value = 1; > put_load(mac.ea, sizeof mac.ea, MFF_ETH_DST, 0, 48, &ofpacts); > + put_load(&value, sizeof value, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1, > + &ofpacts); > ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, 100, > b->header_.uuid.parts[0], &get_arp_match, > &ofpacts, &b->header_.uuid); > > ofpbuf_clear(&ofpacts); > - uint8_t value = 1; > put_load(&value, sizeof value, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1, > &ofpacts); > match_set_dl_src(&lookup_arp_match, mac); > diff --git a/include/ovn/actions.h b/include/ovn/actions.h > index 4a54abe..2b5a63a 100644 > --- a/include/ovn/actions.h > +++ b/include/ovn/actions.h > @@ -75,9 +75,11 @@ struct ovn_extend_table; > OVNACT(GET_ARP, ovnact_get_mac_bind) \ > OVNACT(PUT_ARP, ovnact_put_mac_bind) \ > OVNACT(LOOKUP_ARP, ovnact_lookup_mac_bind) \ > + OVNACT(LOOKUP_ARP_IP, ovnact_lookup_mac_bind_ip) \ > OVNACT(GET_ND, ovnact_get_mac_bind) \ > OVNACT(PUT_ND, ovnact_put_mac_bind) \ > OVNACT(LOOKUP_ND, ovnact_lookup_mac_bind) \ > + OVNACT(LOOKUP_ND_IP, ovnact_lookup_mac_bind_ip) \ > OVNACT(PUT_DHCPV4_OPTS, ovnact_put_opts) \ > OVNACT(PUT_DHCPV6_OPTS, ovnact_put_opts) \ > OVNACT(SET_QUEUE, ovnact_set_queue) \ > @@ -307,6 +309,14 @@ struct ovnact_lookup_mac_bind { > struct expr_field mac; /* 48-bit Ethernet address. */ > }; > > +/* OVNACT_LOOKUP_ARP_IP, OVNACT_LOOKUP_ND_IP. */ > +struct ovnact_lookup_mac_bind_ip { > + struct ovnact ovnact; > + struct expr_field dst; /* 1-bit destination field. */ > + struct expr_field port; /* Logical port name. */ > + struct expr_field ip; /* 32-bit or 128-bit IP address. */ > +}; > + > struct ovnact_gen_option { > const struct gen_opts_map *option; > struct expr_constant_set value; > diff --git a/lib/actions.c b/lib/actions.c > index 22c0e76..41301c8 100644 > --- a/lib/actions.c > +++ b/lib/actions.c > @@ -1953,6 +1953,110 @@ ovnact_lookup_mac_bind_free( > > } > > + > +static void format_lookup_mac_bind_ip( > + const struct ovnact_lookup_mac_bind_ip *lookup_mac, > + struct ds *s, const char *name) > +{ > + expr_field_format(&lookup_mac->dst, s); > + ds_put_format(s, " = %s(", name); > + expr_field_format(&lookup_mac->port, s); > + ds_put_cstr(s, ", "); > + expr_field_format(&lookup_mac->ip, s); > + ds_put_cstr(s, ");"); > +} > + > +static void > +format_LOOKUP_ARP_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, > + struct ds *s) > +{ > + format_lookup_mac_bind_ip(lookup_mac, s, "lookup_arp_ip"); > +} > + > +static void > +format_LOOKUP_ND_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, > + struct ds *s) > +{ > + format_lookup_mac_bind_ip(lookup_mac, s, "lookup_nd_ip"); > +} > + > +static void > +encode_lookup_mac_bind_ip(const struct ovnact_lookup_mac_bind_ip > *lookup_mac, > + enum mf_field_id ip_field, > + const struct ovnact_encode_params *ep, > + struct ofpbuf *ofpacts) > +{ > + const struct arg args[] = { > + { expr_resolve_field(&lookup_mac->port), MFF_LOG_OUTPORT }, > + { expr_resolve_field(&lookup_mac->ip), ip_field }, > + }; > + > + encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > + init_stack(ofpact_put_STACK_PUSH(ofpacts), MFF_ETH_DST); > + > + struct mf_subfield dst = expr_resolve_field(&lookup_mac->dst); > + ovs_assert(dst.field); > + > + put_load(0, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1, ofpacts); > + emit_resubmit(ofpacts, ep->mac_bind_ptable); > + > + struct ofpact_reg_move *orm = ofpact_put_REG_MOVE(ofpacts); > + orm->dst = dst; > + orm->src.field = mf_from_id(MFF_LOG_FLAGS); > + orm->src.ofs = MLF_LOOKUP_MAC_BIT; > + orm->src.n_bits = 1; > + > + init_stack(ofpact_put_STACK_POP(ofpacts), MFF_ETH_DST); > + encode_restore_args(args, ARRAY_SIZE(args), ofpacts); > +} > + > +static void > +encode_LOOKUP_ARP_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, > + const struct ovnact_encode_params *ep, > + struct ofpbuf *ofpacts) > +{ > + encode_lookup_mac_bind_ip(lookup_mac, MFF_REG0, ep, ofpacts); > +} > + > +static void > +encode_LOOKUP_ND_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, > + const struct ovnact_encode_params *ep, > + struct ofpbuf *ofpacts) > +{ > + encode_lookup_mac_bind_ip(lookup_mac, MFF_XXREG0, ep, ofpacts); > +} > + > +static void > +parse_lookup_mac_bind_ip(struct action_context *ctx, > + const struct expr_field *dst, > + int width, > + struct ovnact_lookup_mac_bind_ip *lookup_mac) > +{ > + /* Validate that the destination is a 1-bit, modifiable field. */ > + char *error = expr_type_check(dst, 1, true); > + if (error) { > + lexer_error(ctx->lexer, "%s", error); > + free(error); > + return; > + } > + > + lexer_get(ctx->lexer); /* Skip lookup_arp/lookup_nd. */ > + lexer_get(ctx->lexer); /* Skip '('. * */ > + > + action_parse_field(ctx, 0, false, &lookup_mac->port); > + lexer_force_match(ctx->lexer, LEX_T_COMMA); > + action_parse_field(ctx, width, false, &lookup_mac->ip); > + lexer_force_match(ctx->lexer, LEX_T_RPAREN); > + lookup_mac->dst = *dst; > +} > + > +static void > +ovnact_lookup_mac_bind_ip_free( > + struct ovnact_lookup_mac_bind_ip *lookup_mac OVS_UNUSED) > +{ > + > +} > + > > static void > parse_gen_opt(struct action_context *ctx, struct ovnact_gen_option *o, > @@ -3278,6 +3382,14 @@ parse_set_action(struct action_context *ctx) > && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { > parse_lookup_mac_bind(ctx, &lhs, 128, > ovnact_put_LOOKUP_ND(ctx->ovnacts)); > + } else if (!strcmp(ctx->lexer->token.s, "lookup_arp_ip") > + && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { > + parse_lookup_mac_bind_ip(ctx, &lhs, 32, > + > ovnact_put_LOOKUP_ARP_IP(ctx->ovnacts)); > + } else if (!strcmp(ctx->lexer->token.s, "lookup_nd_ip") > + && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { > + parse_lookup_mac_bind_ip(ctx, &lhs, 128, > + > ovnact_put_LOOKUP_ND_IP(ctx->ovnacts)); > } else { > parse_assignment_action(ctx, false, &lhs); > } > diff --git a/tests/ovn.at b/tests/ovn.at > index b7976c6..12849b4 100644 > --- a/tests/ovn.at > +++ b/tests/ovn.at > @@ -1203,6 +1203,31 @@ reg0[0] = lookup_arp(inport, eth.dst); > reg0[0] = lookup_arp(inport, ip4.src, ip4.dst); > Cannot use 32-bit field ip4.dst[0..31] where 48-bit field is required. > > +# lookup_arp_ip > +reg0[0] = lookup_arp_ip(inport, ip4.dst); > + encodes as > push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[96],pop:NXM_OF_ETH_DST[],pop:NXM_NX_REG0[],pop:NXM_NX_REG15[] > + has prereqs eth.type == 0x800 > +reg1[1] = lookup_arp_ip(inport, arp.spa); > + encodes as > push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_OF_ARP_SPA[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[65],pop:NXM_OF_ETH_DST[],pop:NXM_NX_REG0[],pop:NXM_NX_REG15[] > + has prereqs eth.type == 0x806 > + > +lookup_arp_ip; > + Syntax error at `lookup_arp_ip' expecting action. > +reg0[0] = lookup_arp_ip; > + Syntax error at `lookup_arp_ip' expecting field name. > +reg0[0] = lookup_arp_ip(); > + Syntax error at `)' expecting field name. > +reg0[0] = lookup_arp_ip(inport); > + Syntax error at `)' expecting `,'. > +reg0[0] = lookup_arp_ip(inport ip4.dst); > + Syntax error at `ip4.dst' expecting `,'. > +reg0[0] = lookup_arp_ip(inport, ip4.dst; > + Syntax error at `;' expecting `)'. > +reg0[0] = lookup_arp_ip(inport, ip4.dst, eth.src; > + Syntax error at `,' expecting `)'. > +reg0[0] = lookup_arp_ip(inport, eth.dst); > + Cannot use 48-bit field eth.dst[0..47] where 32-bit field is required. > + > # put_dhcp_opts > reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1); > encodes as > controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause) > @@ -1332,6 +1357,31 @@ reg0[0] = lookup_nd(inport, ip4.src, ip4.dst); > reg0[0] = lookup_nd(inport, ip6.src, ip6.dst); > Cannot use 128-bit field ip6.dst[0..127] where 48-bit field is > required. > > +# lookup_nd_ip > +reg2[0] = lookup_nd_ip(inport, ip6.dst); > + encodes as > push:NXM_NX_REG15[],push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_XXREG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[32],pop:NXM_OF_ETH_DST[],pop:NXM_NX_XXREG0[],pop:NXM_NX_REG15[] > + has prereqs eth.type == 0x86dd > +reg3[0] = lookup_nd_ip(inport, nd.target); > + encodes as > push:NXM_NX_REG15[],push:NXM_NX_XXREG0[],push:NXM_NX_ND_TARGET[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_XXREG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[0],pop:NXM_OF_ETH_DST[],pop:NXM_NX_XXREG0[],pop:NXM_NX_REG15[] > + has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) && eth.type == > 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && > icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == > 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || > eth.type == 0x86dd) > + > +lookup_nd_ip; > + Syntax error at `lookup_nd_ip' expecting action. > +reg0[0] = lookup_nd_ip; > + Syntax error at `lookup_nd_ip' expecting field name. > +reg0[0] = lookup_nd_ip(); > + Syntax error at `)' expecting field name. > +reg0[0] = lookup_nd_ip(inport); > + Syntax error at `)' expecting `,'. > +reg0[0] = lookup_nd_ip(inport ip6.dst); > + Syntax error at `ip6.dst' expecting `,'. > +reg0[0] = lookup_nd_ip(inport, ip6.dst; > + Syntax error at `;' expecting `)'. > +reg0[0] = lookup_nd_ip(inport, eth.dst); > + Cannot use 48-bit field eth.dst[0..47] where 128-bit field is > required. > +reg0[0] = lookup_nd_ip(inport, ip4.src); > + Cannot use 32-bit field ip4.src[0..31] where 128-bit field is > required. > + > # set_queue > set_queue(0); > encodes as set_queue:0 > diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c > index 146560c..ae0a59e 100644 > --- a/utilities/ovn-trace.c > +++ b/utilities/ovn-trace.c > @@ -582,13 +582,13 @@ ovntrace_mac_binding_find(const struct > ovntrace_datapath *dp, > static const struct ovntrace_mac_binding * > ovntrace_mac_binding_find_mac_ip(const struct ovntrace_datapath *dp, > uint16_t port_key, const struct in6_addr > *ip, > - struct eth_addr mac) > + struct eth_addr *mac) > { > const struct ovntrace_mac_binding *bind; > HMAP_FOR_EACH_WITH_HASH (bind, node, hash_mac_binding(port_key, ip), > &dp->mac_bindings) { > if (bind->port_key == port_key && ipv6_addr_equals(ip, &bind->ip) > - && eth_addr_equals(bind->mac, mac)) { > + && (!mac || eth_addr_equals(bind->mac, *mac))) { > return bind; > } > } > @@ -1771,7 +1771,7 @@ execute_lookup_mac_bind(const struct > ovnact_lookup_mac_bind *bind, > mf_read_subfield(&mac_sf, uflow, &mac_sv); > > const struct ovntrace_mac_binding *binding > - = ovntrace_mac_binding_find_mac_ip(dp, port_key, &ip, mac_sv.mac); > + = ovntrace_mac_binding_find_mac_ip(dp, port_key, &ip, > &mac_sv.mac); > > struct mf_subfield dst = expr_resolve_field(&bind->dst); > uint8_t val = 0; > @@ -1790,6 +1790,44 @@ execute_lookup_mac_bind(const struct > ovnact_lookup_mac_bind *bind, > } > > static void > +execute_lookup_mac_bind_ip(const struct ovnact_lookup_mac_bind_ip *bind, > + const struct ovntrace_datapath *dp, > + struct flow *uflow, > + struct ovs_list *super) > +{ > + /* Get logical port number.*/ > + struct mf_subfield port_sf = expr_resolve_field(&bind->port); > + ovs_assert(port_sf.n_bits == 32); > + uint32_t port_key = mf_get_subfield(&port_sf, uflow); > + > + /* Get IP address. */ > + struct mf_subfield ip_sf = expr_resolve_field(&bind->ip); > + ovs_assert(ip_sf.n_bits == 32 || ip_sf.n_bits == 128); > + union mf_subvalue ip_sv; > + mf_read_subfield(&ip_sf, uflow, &ip_sv); > + struct in6_addr ip = (ip_sf.n_bits == 32 > + ? in6_addr_mapped_ipv4(ip_sv.ipv4) > + : ip_sv.ipv6); > + > + const struct ovntrace_mac_binding *binding > + = ovntrace_mac_binding_find_mac_ip(dp, port_key, &ip, NULL); > + > + struct mf_subfield dst = expr_resolve_field(&bind->dst); > + uint8_t val = 0; > + > + if (binding) { > + val = 1; > + ovntrace_node_append(super, OVNTRACE_NODE_ACTION, > + "/* MAC binding for <TODO: ipv4/v6> found. > */"); > + } else { > + ovntrace_node_append(super, OVNTRACE_NODE_ACTION, > + "/* lookup failed - No MAC binding. */"); > + } > + union mf_subvalue sv = { .u8_val = val }; > + mf_write_subfield_flow(&dst, &sv, uflow); > +} > + > +static void > execute_put_opts(const struct ovnact_put_opts *po, > const char *name, struct flow *uflow, > struct ovs_list *super) > @@ -2216,6 +2254,16 @@ trace_actions(const struct ovnact *ovnacts, size_t > ovnacts_len, > execute_lookup_mac_bind(ovnact_get_LOOKUP_ND(a), dp, uflow, > super); > break; > > + case OVNACT_LOOKUP_ARP_IP: > + execute_lookup_mac_bind_ip(ovnact_get_LOOKUP_ARP_IP(a), dp, > uflow, > + super); > + break; > + > + case OVNACT_LOOKUP_ND_IP: > + execute_lookup_mac_bind_ip(ovnact_get_LOOKUP_ND_IP(a), dp, > uflow, > + super); > + break; > + > case OVNACT_PUT_DHCPV4_OPTS: > execute_put_dhcp_opts(ovnact_get_PUT_DHCPV4_OPTS(a), > "put_dhcp_opts", uflow, super); > -- > 2.1.0 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > >
On Thu, Jun 11, 2020 at 9:59 AM Numan Siddique <nusiddiq@redhat.com> wrote: > > On Thu, Jun 11, 2020 at 12:31 AM Han Zhou <hzhou@ovn.org> wrote: > > > lookup_arp_ip and lookup_nd_ip are added to lookup if an entry exists > > in MAC bindings for a given IP address, for IPv4 and IPv6 respectively. > > > > Signed-off-by: Han Zhou <hzhou@ovn.org> > > > > Hi Han, > > I know this is RFC. I was just going through it and noticed that this patch > needs to document the new actions in ovn-sb.xml. Sure, I will add. > > Thanks > Numan > > --- > > controller/lflow.c | 4 +- > > include/ovn/actions.h | 10 +++++ > > lib/actions.c | 112 > > ++++++++++++++++++++++++++++++++++++++++++++++++++ > > tests/ovn.at | 50 ++++++++++++++++++++++ > > utilities/ovn-trace.c | 54 ++++++++++++++++++++++-- > > 5 files changed, 226 insertions(+), 4 deletions(-) > > > > diff --git a/controller/lflow.c b/controller/lflow.c > > index 01214a3..e45ed33 100644 > > --- a/controller/lflow.c > > +++ b/controller/lflow.c > > @@ -761,13 +761,15 @@ consider_neighbor_flow(struct ovsdb_idl_index > > *sbrec_port_binding_by_name, > > > > uint64_t stub[1024 / 8]; > > struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub); > > + uint8_t value = 1; > > put_load(mac.ea, sizeof mac.ea, MFF_ETH_DST, 0, 48, &ofpacts); > > + put_load(&value, sizeof value, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1, > > + &ofpacts); > > ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, 100, > > b->header_.uuid.parts[0], &get_arp_match, > > &ofpacts, &b->header_.uuid); > > > > ofpbuf_clear(&ofpacts); > > - uint8_t value = 1; > > put_load(&value, sizeof value, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1, > > &ofpacts); > > match_set_dl_src(&lookup_arp_match, mac); > > diff --git a/include/ovn/actions.h b/include/ovn/actions.h > > index 4a54abe..2b5a63a 100644 > > --- a/include/ovn/actions.h > > +++ b/include/ovn/actions.h > > @@ -75,9 +75,11 @@ struct ovn_extend_table; > > OVNACT(GET_ARP, ovnact_get_mac_bind) \ > > OVNACT(PUT_ARP, ovnact_put_mac_bind) \ > > OVNACT(LOOKUP_ARP, ovnact_lookup_mac_bind) \ > > + OVNACT(LOOKUP_ARP_IP, ovnact_lookup_mac_bind_ip) \ > > OVNACT(GET_ND, ovnact_get_mac_bind) \ > > OVNACT(PUT_ND, ovnact_put_mac_bind) \ > > OVNACT(LOOKUP_ND, ovnact_lookup_mac_bind) \ > > + OVNACT(LOOKUP_ND_IP, ovnact_lookup_mac_bind_ip) \ > > OVNACT(PUT_DHCPV4_OPTS, ovnact_put_opts) \ > > OVNACT(PUT_DHCPV6_OPTS, ovnact_put_opts) \ > > OVNACT(SET_QUEUE, ovnact_set_queue) \ > > @@ -307,6 +309,14 @@ struct ovnact_lookup_mac_bind { > > struct expr_field mac; /* 48-bit Ethernet address. */ > > }; > > > > +/* OVNACT_LOOKUP_ARP_IP, OVNACT_LOOKUP_ND_IP. */ > > +struct ovnact_lookup_mac_bind_ip { > > + struct ovnact ovnact; > > + struct expr_field dst; /* 1-bit destination field. */ > > + struct expr_field port; /* Logical port name. */ > > + struct expr_field ip; /* 32-bit or 128-bit IP address. */ > > +}; > > + > > struct ovnact_gen_option { > > const struct gen_opts_map *option; > > struct expr_constant_set value; > > diff --git a/lib/actions.c b/lib/actions.c > > index 22c0e76..41301c8 100644 > > --- a/lib/actions.c > > +++ b/lib/actions.c > > @@ -1953,6 +1953,110 @@ ovnact_lookup_mac_bind_free( > > > > } > > > > + > > +static void format_lookup_mac_bind_ip( > > + const struct ovnact_lookup_mac_bind_ip *lookup_mac, > > + struct ds *s, const char *name) > > +{ > > + expr_field_format(&lookup_mac->dst, s); > > + ds_put_format(s, " = %s(", name); > > + expr_field_format(&lookup_mac->port, s); > > + ds_put_cstr(s, ", "); > > + expr_field_format(&lookup_mac->ip, s); > > + ds_put_cstr(s, ");"); > > +} > > + > > +static void > > +format_LOOKUP_ARP_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, > > + struct ds *s) > > +{ > > + format_lookup_mac_bind_ip(lookup_mac, s, "lookup_arp_ip"); > > +} > > + > > +static void > > +format_LOOKUP_ND_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, > > + struct ds *s) > > +{ > > + format_lookup_mac_bind_ip(lookup_mac, s, "lookup_nd_ip"); > > +} > > + > > +static void > > +encode_lookup_mac_bind_ip(const struct ovnact_lookup_mac_bind_ip > > *lookup_mac, > > + enum mf_field_id ip_field, > > + const struct ovnact_encode_params *ep, > > + struct ofpbuf *ofpacts) > > +{ > > + const struct arg args[] = { > > + { expr_resolve_field(&lookup_mac->port), MFF_LOG_OUTPORT }, > > + { expr_resolve_field(&lookup_mac->ip), ip_field }, > > + }; > > + > > + encode_setup_args(args, ARRAY_SIZE(args), ofpacts); > > + init_stack(ofpact_put_STACK_PUSH(ofpacts), MFF_ETH_DST); > > + > > + struct mf_subfield dst = expr_resolve_field(&lookup_mac->dst); > > + ovs_assert(dst.field); > > + > > + put_load(0, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1, ofpacts); > > + emit_resubmit(ofpacts, ep->mac_bind_ptable); > > + > > + struct ofpact_reg_move *orm = ofpact_put_REG_MOVE(ofpacts); > > + orm->dst = dst; > > + orm->src.field = mf_from_id(MFF_LOG_FLAGS); > > + orm->src.ofs = MLF_LOOKUP_MAC_BIT; > > + orm->src.n_bits = 1; > > + > > + init_stack(ofpact_put_STACK_POP(ofpacts), MFF_ETH_DST); > > + encode_restore_args(args, ARRAY_SIZE(args), ofpacts); > > +} > > + > > +static void > > +encode_LOOKUP_ARP_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, > > + const struct ovnact_encode_params *ep, > > + struct ofpbuf *ofpacts) > > +{ > > + encode_lookup_mac_bind_ip(lookup_mac, MFF_REG0, ep, ofpacts); > > +} > > + > > +static void > > +encode_LOOKUP_ND_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, > > + const struct ovnact_encode_params *ep, > > + struct ofpbuf *ofpacts) > > +{ > > + encode_lookup_mac_bind_ip(lookup_mac, MFF_XXREG0, ep, ofpacts); > > +} > > + > > +static void > > +parse_lookup_mac_bind_ip(struct action_context *ctx, > > + const struct expr_field *dst, > > + int width, > > + struct ovnact_lookup_mac_bind_ip *lookup_mac) > > +{ > > + /* Validate that the destination is a 1-bit, modifiable field. */ > > + char *error = expr_type_check(dst, 1, true); > > + if (error) { > > + lexer_error(ctx->lexer, "%s", error); > > + free(error); > > + return; > > + } > > + > > + lexer_get(ctx->lexer); /* Skip lookup_arp/lookup_nd. */ > > + lexer_get(ctx->lexer); /* Skip '('. * */ > > + > > + action_parse_field(ctx, 0, false, &lookup_mac->port); > > + lexer_force_match(ctx->lexer, LEX_T_COMMA); > > + action_parse_field(ctx, width, false, &lookup_mac->ip); > > + lexer_force_match(ctx->lexer, LEX_T_RPAREN); > > + lookup_mac->dst = *dst; > > +} > > + > > +static void > > +ovnact_lookup_mac_bind_ip_free( > > + struct ovnact_lookup_mac_bind_ip *lookup_mac OVS_UNUSED) > > +{ > > + > > +} > > + > > > > static void > > parse_gen_opt(struct action_context *ctx, struct ovnact_gen_option *o, > > @@ -3278,6 +3382,14 @@ parse_set_action(struct action_context *ctx) > > && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { > > parse_lookup_mac_bind(ctx, &lhs, 128, > > ovnact_put_LOOKUP_ND(ctx->ovnacts)); > > + } else if (!strcmp(ctx->lexer->token.s, "lookup_arp_ip") > > + && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { > > + parse_lookup_mac_bind_ip(ctx, &lhs, 32, > > + > > ovnact_put_LOOKUP_ARP_IP(ctx->ovnacts)); > > + } else if (!strcmp(ctx->lexer->token.s, "lookup_nd_ip") > > + && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { > > + parse_lookup_mac_bind_ip(ctx, &lhs, 128, > > + > > ovnact_put_LOOKUP_ND_IP(ctx->ovnacts)); > > } else { > > parse_assignment_action(ctx, false, &lhs); > > } > > diff --git a/tests/ovn.at b/tests/ovn.at > > index b7976c6..12849b4 100644 > > --- a/tests/ovn.at > > +++ b/tests/ovn.at > > @@ -1203,6 +1203,31 @@ reg0[0] = lookup_arp(inport, eth.dst); > > reg0[0] = lookup_arp(inport, ip4.src, ip4.dst); > > Cannot use 32-bit field ip4.dst[0..31] where 48-bit field is required. > > > > +# lookup_arp_ip > > +reg0[0] = lookup_arp_ip(inport, ip4.dst); > > + encodes as > > push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[96],pop:NXM_OF_ETH_DST[],pop:NXM_NX_REG0[],pop:NXM_NX_REG15[] > > + has prereqs eth.type == 0x800 > > +reg1[1] = lookup_arp_ip(inport, arp.spa); > > + encodes as > > push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_OF_ARP_SPA[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[65],pop:NXM_OF_ETH_DST[],pop:NXM_NX_REG0[],pop:NXM_NX_REG15[] > > + has prereqs eth.type == 0x806 > > + > > +lookup_arp_ip; > > + Syntax error at `lookup_arp_ip' expecting action. > > +reg0[0] = lookup_arp_ip; > > + Syntax error at `lookup_arp_ip' expecting field name. > > +reg0[0] = lookup_arp_ip(); > > + Syntax error at `)' expecting field name. > > +reg0[0] = lookup_arp_ip(inport); > > + Syntax error at `)' expecting `,'. > > +reg0[0] = lookup_arp_ip(inport ip4.dst); > > + Syntax error at `ip4.dst' expecting `,'. > > +reg0[0] = lookup_arp_ip(inport, ip4.dst; > > + Syntax error at `;' expecting `)'. > > +reg0[0] = lookup_arp_ip(inport, ip4.dst, eth.src; > > + Syntax error at `,' expecting `)'. > > +reg0[0] = lookup_arp_ip(inport, eth.dst); > > + Cannot use 48-bit field eth.dst[0..47] where 32-bit field is required. > > + > > # put_dhcp_opts > > reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1); > > encodes as > > controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause) > > @@ -1332,6 +1357,31 @@ reg0[0] = lookup_nd(inport, ip4.src, ip4.dst); > > reg0[0] = lookup_nd(inport, ip6.src, ip6.dst); > > Cannot use 128-bit field ip6.dst[0..127] where 48-bit field is > > required. > > > > +# lookup_nd_ip > > +reg2[0] = lookup_nd_ip(inport, ip6.dst); > > + encodes as > > push:NXM_NX_REG15[],push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_XXREG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[32],pop:NXM_OF_ETH_DST[],pop:NXM_NX_XXREG0[],pop:NXM_NX_REG15[] > > + has prereqs eth.type == 0x86dd > > +reg3[0] = lookup_nd_ip(inport, nd.target); > > + encodes as > > push:NXM_NX_REG15[],push:NXM_NX_XXREG0[],push:NXM_NX_ND_TARGET[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_XXREG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[0],pop:NXM_OF_ETH_DST[],pop:NXM_NX_XXREG0[],pop:NXM_NX_REG15[] > > + has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) && eth.type == > > 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && > > icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == > > 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || > > eth.type == 0x86dd) > > + > > +lookup_nd_ip; > > + Syntax error at `lookup_nd_ip' expecting action. > > +reg0[0] = lookup_nd_ip; > > + Syntax error at `lookup_nd_ip' expecting field name. > > +reg0[0] = lookup_nd_ip(); > > + Syntax error at `)' expecting field name. > > +reg0[0] = lookup_nd_ip(inport); > > + Syntax error at `)' expecting `,'. > > +reg0[0] = lookup_nd_ip(inport ip6.dst); > > + Syntax error at `ip6.dst' expecting `,'. > > +reg0[0] = lookup_nd_ip(inport, ip6.dst; > > + Syntax error at `;' expecting `)'. > > +reg0[0] = lookup_nd_ip(inport, eth.dst); > > + Cannot use 48-bit field eth.dst[0..47] where 128-bit field is > > required. > > +reg0[0] = lookup_nd_ip(inport, ip4.src); > > + Cannot use 32-bit field ip4.src[0..31] where 128-bit field is > > required. > > + > > # set_queue > > set_queue(0); > > encodes as set_queue:0 > > diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c > > index 146560c..ae0a59e 100644 > > --- a/utilities/ovn-trace.c > > +++ b/utilities/ovn-trace.c > > @@ -582,13 +582,13 @@ ovntrace_mac_binding_find(const struct > > ovntrace_datapath *dp, > > static const struct ovntrace_mac_binding * > > ovntrace_mac_binding_find_mac_ip(const struct ovntrace_datapath *dp, > > uint16_t port_key, const struct in6_addr > > *ip, > > - struct eth_addr mac) > > + struct eth_addr *mac) > > { > > const struct ovntrace_mac_binding *bind; > > HMAP_FOR_EACH_WITH_HASH (bind, node, hash_mac_binding(port_key, ip), > > &dp->mac_bindings) { > > if (bind->port_key == port_key && ipv6_addr_equals(ip, &bind->ip) > > - && eth_addr_equals(bind->mac, mac)) { > > + && (!mac || eth_addr_equals(bind->mac, *mac))) { > > return bind; > > } > > } > > @@ -1771,7 +1771,7 @@ execute_lookup_mac_bind(const struct > > ovnact_lookup_mac_bind *bind, > > mf_read_subfield(&mac_sf, uflow, &mac_sv); > > > > const struct ovntrace_mac_binding *binding > > - = ovntrace_mac_binding_find_mac_ip(dp, port_key, &ip, mac_sv.mac); > > + = ovntrace_mac_binding_find_mac_ip(dp, port_key, &ip, > > &mac_sv.mac); > > > > struct mf_subfield dst = expr_resolve_field(&bind->dst); > > uint8_t val = 0; > > @@ -1790,6 +1790,44 @@ execute_lookup_mac_bind(const struct > > ovnact_lookup_mac_bind *bind, > > } > > > > static void > > +execute_lookup_mac_bind_ip(const struct ovnact_lookup_mac_bind_ip *bind, > > + const struct ovntrace_datapath *dp, > > + struct flow *uflow, > > + struct ovs_list *super) > > +{ > > + /* Get logical port number.*/ > > + struct mf_subfield port_sf = expr_resolve_field(&bind->port); > > + ovs_assert(port_sf.n_bits == 32); > > + uint32_t port_key = mf_get_subfield(&port_sf, uflow); > > + > > + /* Get IP address. */ > > + struct mf_subfield ip_sf = expr_resolve_field(&bind->ip); > > + ovs_assert(ip_sf.n_bits == 32 || ip_sf.n_bits == 128); > > + union mf_subvalue ip_sv; > > + mf_read_subfield(&ip_sf, uflow, &ip_sv); > > + struct in6_addr ip = (ip_sf.n_bits == 32 > > + ? in6_addr_mapped_ipv4(ip_sv.ipv4) > > + : ip_sv.ipv6); > > + > > + const struct ovntrace_mac_binding *binding > > + = ovntrace_mac_binding_find_mac_ip(dp, port_key, &ip, NULL); > > + > > + struct mf_subfield dst = expr_resolve_field(&bind->dst); > > + uint8_t val = 0; > > + > > + if (binding) { > > + val = 1; > > + ovntrace_node_append(super, OVNTRACE_NODE_ACTION, > > + "/* MAC binding for <TODO: ipv4/v6> found. > > */"); > > + } else { > > + ovntrace_node_append(super, OVNTRACE_NODE_ACTION, > > + "/* lookup failed - No MAC binding. */"); > > + } > > + union mf_subvalue sv = { .u8_val = val }; > > + mf_write_subfield_flow(&dst, &sv, uflow); > > +} > > + > > +static void > > execute_put_opts(const struct ovnact_put_opts *po, > > const char *name, struct flow *uflow, > > struct ovs_list *super) > > @@ -2216,6 +2254,16 @@ trace_actions(const struct ovnact *ovnacts, size_t > > ovnacts_len, > > execute_lookup_mac_bind(ovnact_get_LOOKUP_ND(a), dp, uflow, > > super); > > break; > > > > + case OVNACT_LOOKUP_ARP_IP: > > + execute_lookup_mac_bind_ip(ovnact_get_LOOKUP_ARP_IP(a), dp, > > uflow, > > + super); > > + break; > > + > > + case OVNACT_LOOKUP_ND_IP: > > + execute_lookup_mac_bind_ip(ovnact_get_LOOKUP_ND_IP(a), dp, > > uflow, > > + super); > > + break; > > + > > case OVNACT_PUT_DHCPV4_OPTS: > > execute_put_dhcp_opts(ovnact_get_PUT_DHCPV4_OPTS(a), > > "put_dhcp_opts", uflow, super); > > -- > > 2.1.0 > > > > _______________________________________________ > > dev mailing list > > dev@openvswitch.org > > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > > > > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev
diff --git a/controller/lflow.c b/controller/lflow.c index 01214a3..e45ed33 100644 --- a/controller/lflow.c +++ b/controller/lflow.c @@ -761,13 +761,15 @@ consider_neighbor_flow(struct ovsdb_idl_index *sbrec_port_binding_by_name, uint64_t stub[1024 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(stub); + uint8_t value = 1; put_load(mac.ea, sizeof mac.ea, MFF_ETH_DST, 0, 48, &ofpacts); + put_load(&value, sizeof value, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1, + &ofpacts); ofctrl_add_flow(flow_table, OFTABLE_MAC_BINDING, 100, b->header_.uuid.parts[0], &get_arp_match, &ofpacts, &b->header_.uuid); ofpbuf_clear(&ofpacts); - uint8_t value = 1; put_load(&value, sizeof value, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1, &ofpacts); match_set_dl_src(&lookup_arp_match, mac); diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 4a54abe..2b5a63a 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -75,9 +75,11 @@ struct ovn_extend_table; OVNACT(GET_ARP, ovnact_get_mac_bind) \ OVNACT(PUT_ARP, ovnact_put_mac_bind) \ OVNACT(LOOKUP_ARP, ovnact_lookup_mac_bind) \ + OVNACT(LOOKUP_ARP_IP, ovnact_lookup_mac_bind_ip) \ OVNACT(GET_ND, ovnact_get_mac_bind) \ OVNACT(PUT_ND, ovnact_put_mac_bind) \ OVNACT(LOOKUP_ND, ovnact_lookup_mac_bind) \ + OVNACT(LOOKUP_ND_IP, ovnact_lookup_mac_bind_ip) \ OVNACT(PUT_DHCPV4_OPTS, ovnact_put_opts) \ OVNACT(PUT_DHCPV6_OPTS, ovnact_put_opts) \ OVNACT(SET_QUEUE, ovnact_set_queue) \ @@ -307,6 +309,14 @@ struct ovnact_lookup_mac_bind { struct expr_field mac; /* 48-bit Ethernet address. */ }; +/* OVNACT_LOOKUP_ARP_IP, OVNACT_LOOKUP_ND_IP. */ +struct ovnact_lookup_mac_bind_ip { + struct ovnact ovnact; + struct expr_field dst; /* 1-bit destination field. */ + struct expr_field port; /* Logical port name. */ + struct expr_field ip; /* 32-bit or 128-bit IP address. */ +}; + struct ovnact_gen_option { const struct gen_opts_map *option; struct expr_constant_set value; diff --git a/lib/actions.c b/lib/actions.c index 22c0e76..41301c8 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -1953,6 +1953,110 @@ ovnact_lookup_mac_bind_free( } + +static void format_lookup_mac_bind_ip( + const struct ovnact_lookup_mac_bind_ip *lookup_mac, + struct ds *s, const char *name) +{ + expr_field_format(&lookup_mac->dst, s); + ds_put_format(s, " = %s(", name); + expr_field_format(&lookup_mac->port, s); + ds_put_cstr(s, ", "); + expr_field_format(&lookup_mac->ip, s); + ds_put_cstr(s, ");"); +} + +static void +format_LOOKUP_ARP_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, + struct ds *s) +{ + format_lookup_mac_bind_ip(lookup_mac, s, "lookup_arp_ip"); +} + +static void +format_LOOKUP_ND_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, + struct ds *s) +{ + format_lookup_mac_bind_ip(lookup_mac, s, "lookup_nd_ip"); +} + +static void +encode_lookup_mac_bind_ip(const struct ovnact_lookup_mac_bind_ip *lookup_mac, + enum mf_field_id ip_field, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + const struct arg args[] = { + { expr_resolve_field(&lookup_mac->port), MFF_LOG_OUTPORT }, + { expr_resolve_field(&lookup_mac->ip), ip_field }, + }; + + encode_setup_args(args, ARRAY_SIZE(args), ofpacts); + init_stack(ofpact_put_STACK_PUSH(ofpacts), MFF_ETH_DST); + + struct mf_subfield dst = expr_resolve_field(&lookup_mac->dst); + ovs_assert(dst.field); + + put_load(0, MFF_LOG_FLAGS, MLF_LOOKUP_MAC_BIT, 1, ofpacts); + emit_resubmit(ofpacts, ep->mac_bind_ptable); + + struct ofpact_reg_move *orm = ofpact_put_REG_MOVE(ofpacts); + orm->dst = dst; + orm->src.field = mf_from_id(MFF_LOG_FLAGS); + orm->src.ofs = MLF_LOOKUP_MAC_BIT; + orm->src.n_bits = 1; + + init_stack(ofpact_put_STACK_POP(ofpacts), MFF_ETH_DST); + encode_restore_args(args, ARRAY_SIZE(args), ofpacts); +} + +static void +encode_LOOKUP_ARP_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_lookup_mac_bind_ip(lookup_mac, MFF_REG0, ep, ofpacts); +} + +static void +encode_LOOKUP_ND_IP(const struct ovnact_lookup_mac_bind_ip *lookup_mac, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_lookup_mac_bind_ip(lookup_mac, MFF_XXREG0, ep, ofpacts); +} + +static void +parse_lookup_mac_bind_ip(struct action_context *ctx, + const struct expr_field *dst, + int width, + struct ovnact_lookup_mac_bind_ip *lookup_mac) +{ + /* Validate that the destination is a 1-bit, modifiable field. */ + char *error = expr_type_check(dst, 1, true); + if (error) { + lexer_error(ctx->lexer, "%s", error); + free(error); + return; + } + + lexer_get(ctx->lexer); /* Skip lookup_arp/lookup_nd. */ + lexer_get(ctx->lexer); /* Skip '('. * */ + + action_parse_field(ctx, 0, false, &lookup_mac->port); + lexer_force_match(ctx->lexer, LEX_T_COMMA); + action_parse_field(ctx, width, false, &lookup_mac->ip); + lexer_force_match(ctx->lexer, LEX_T_RPAREN); + lookup_mac->dst = *dst; +} + +static void +ovnact_lookup_mac_bind_ip_free( + struct ovnact_lookup_mac_bind_ip *lookup_mac OVS_UNUSED) +{ + +} + static void parse_gen_opt(struct action_context *ctx, struct ovnact_gen_option *o, @@ -3278,6 +3382,14 @@ parse_set_action(struct action_context *ctx) && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { parse_lookup_mac_bind(ctx, &lhs, 128, ovnact_put_LOOKUP_ND(ctx->ovnacts)); + } else if (!strcmp(ctx->lexer->token.s, "lookup_arp_ip") + && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { + parse_lookup_mac_bind_ip(ctx, &lhs, 32, + ovnact_put_LOOKUP_ARP_IP(ctx->ovnacts)); + } else if (!strcmp(ctx->lexer->token.s, "lookup_nd_ip") + && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) { + parse_lookup_mac_bind_ip(ctx, &lhs, 128, + ovnact_put_LOOKUP_ND_IP(ctx->ovnacts)); } else { parse_assignment_action(ctx, false, &lhs); } diff --git a/tests/ovn.at b/tests/ovn.at index b7976c6..12849b4 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1203,6 +1203,31 @@ reg0[0] = lookup_arp(inport, eth.dst); reg0[0] = lookup_arp(inport, ip4.src, ip4.dst); Cannot use 32-bit field ip4.dst[0..31] where 48-bit field is required. +# lookup_arp_ip +reg0[0] = lookup_arp_ip(inport, ip4.dst); + encodes as push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_OF_IP_DST[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[96],pop:NXM_OF_ETH_DST[],pop:NXM_NX_REG0[],pop:NXM_NX_REG15[] + has prereqs eth.type == 0x800 +reg1[1] = lookup_arp_ip(inport, arp.spa); + encodes as push:NXM_NX_REG15[],push:NXM_NX_REG0[],push:NXM_OF_ARP_SPA[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_REG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[65],pop:NXM_OF_ETH_DST[],pop:NXM_NX_REG0[],pop:NXM_NX_REG15[] + has prereqs eth.type == 0x806 + +lookup_arp_ip; + Syntax error at `lookup_arp_ip' expecting action. +reg0[0] = lookup_arp_ip; + Syntax error at `lookup_arp_ip' expecting field name. +reg0[0] = lookup_arp_ip(); + Syntax error at `)' expecting field name. +reg0[0] = lookup_arp_ip(inport); + Syntax error at `)' expecting `,'. +reg0[0] = lookup_arp_ip(inport ip4.dst); + Syntax error at `ip4.dst' expecting `,'. +reg0[0] = lookup_arp_ip(inport, ip4.dst; + Syntax error at `;' expecting `)'. +reg0[0] = lookup_arp_ip(inport, ip4.dst, eth.src; + Syntax error at `,' expecting `)'. +reg0[0] = lookup_arp_ip(inport, eth.dst); + Cannot use 48-bit field eth.dst[0..47] where 32-bit field is required. + # put_dhcp_opts reg1[0] = put_dhcp_opts(offerip = 1.2.3.4, router = 10.0.0.1); encodes as controller(userdata=00.00.00.02.00.00.00.00.00.01.de.10.00.00.00.40.01.02.03.04.03.04.0a.00.00.01,pause) @@ -1332,6 +1357,31 @@ reg0[0] = lookup_nd(inport, ip4.src, ip4.dst); reg0[0] = lookup_nd(inport, ip6.src, ip6.dst); Cannot use 128-bit field ip6.dst[0..127] where 48-bit field is required. +# lookup_nd_ip +reg2[0] = lookup_nd_ip(inport, ip6.dst); + encodes as push:NXM_NX_REG15[],push:NXM_NX_XXREG0[],push:NXM_NX_IPV6_DST[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_XXREG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[32],pop:NXM_OF_ETH_DST[],pop:NXM_NX_XXREG0[],pop:NXM_NX_REG15[] + has prereqs eth.type == 0x86dd +reg3[0] = lookup_nd_ip(inport, nd.target); + encodes as push:NXM_NX_REG15[],push:NXM_NX_XXREG0[],push:NXM_NX_ND_TARGET[],push:NXM_NX_REG14[],pop:NXM_NX_REG15[],pop:NXM_NX_XXREG0[],push:NXM_OF_ETH_DST[],set_field:0/0x40->reg10,resubmit(,66),move:NXM_NX_REG10[6]->NXM_NX_XXREG0[0],pop:NXM_OF_ETH_DST[],pop:NXM_NX_XXREG0[],pop:NXM_NX_REG15[] + has prereqs (icmp6.type == 0x87 || icmp6.type == 0x88) && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && icmp6.code == 0 && eth.type == 0x86dd && ip.proto == 0x3a && (eth.type == 0x800 || eth.type == 0x86dd) && ip.ttl == 0xff && (eth.type == 0x800 || eth.type == 0x86dd) + +lookup_nd_ip; + Syntax error at `lookup_nd_ip' expecting action. +reg0[0] = lookup_nd_ip; + Syntax error at `lookup_nd_ip' expecting field name. +reg0[0] = lookup_nd_ip(); + Syntax error at `)' expecting field name. +reg0[0] = lookup_nd_ip(inport); + Syntax error at `)' expecting `,'. +reg0[0] = lookup_nd_ip(inport ip6.dst); + Syntax error at `ip6.dst' expecting `,'. +reg0[0] = lookup_nd_ip(inport, ip6.dst; + Syntax error at `;' expecting `)'. +reg0[0] = lookup_nd_ip(inport, eth.dst); + Cannot use 48-bit field eth.dst[0..47] where 128-bit field is required. +reg0[0] = lookup_nd_ip(inport, ip4.src); + Cannot use 32-bit field ip4.src[0..31] where 128-bit field is required. + # set_queue set_queue(0); encodes as set_queue:0 diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 146560c..ae0a59e 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -582,13 +582,13 @@ ovntrace_mac_binding_find(const struct ovntrace_datapath *dp, static const struct ovntrace_mac_binding * ovntrace_mac_binding_find_mac_ip(const struct ovntrace_datapath *dp, uint16_t port_key, const struct in6_addr *ip, - struct eth_addr mac) + struct eth_addr *mac) { const struct ovntrace_mac_binding *bind; HMAP_FOR_EACH_WITH_HASH (bind, node, hash_mac_binding(port_key, ip), &dp->mac_bindings) { if (bind->port_key == port_key && ipv6_addr_equals(ip, &bind->ip) - && eth_addr_equals(bind->mac, mac)) { + && (!mac || eth_addr_equals(bind->mac, *mac))) { return bind; } } @@ -1771,7 +1771,7 @@ execute_lookup_mac_bind(const struct ovnact_lookup_mac_bind *bind, mf_read_subfield(&mac_sf, uflow, &mac_sv); const struct ovntrace_mac_binding *binding - = ovntrace_mac_binding_find_mac_ip(dp, port_key, &ip, mac_sv.mac); + = ovntrace_mac_binding_find_mac_ip(dp, port_key, &ip, &mac_sv.mac); struct mf_subfield dst = expr_resolve_field(&bind->dst); uint8_t val = 0; @@ -1790,6 +1790,44 @@ execute_lookup_mac_bind(const struct ovnact_lookup_mac_bind *bind, } static void +execute_lookup_mac_bind_ip(const struct ovnact_lookup_mac_bind_ip *bind, + const struct ovntrace_datapath *dp, + struct flow *uflow, + struct ovs_list *super) +{ + /* Get logical port number.*/ + struct mf_subfield port_sf = expr_resolve_field(&bind->port); + ovs_assert(port_sf.n_bits == 32); + uint32_t port_key = mf_get_subfield(&port_sf, uflow); + + /* Get IP address. */ + struct mf_subfield ip_sf = expr_resolve_field(&bind->ip); + ovs_assert(ip_sf.n_bits == 32 || ip_sf.n_bits == 128); + union mf_subvalue ip_sv; + mf_read_subfield(&ip_sf, uflow, &ip_sv); + struct in6_addr ip = (ip_sf.n_bits == 32 + ? in6_addr_mapped_ipv4(ip_sv.ipv4) + : ip_sv.ipv6); + + const struct ovntrace_mac_binding *binding + = ovntrace_mac_binding_find_mac_ip(dp, port_key, &ip, NULL); + + struct mf_subfield dst = expr_resolve_field(&bind->dst); + uint8_t val = 0; + + if (binding) { + val = 1; + ovntrace_node_append(super, OVNTRACE_NODE_ACTION, + "/* MAC binding for <TODO: ipv4/v6> found. */"); + } else { + ovntrace_node_append(super, OVNTRACE_NODE_ACTION, + "/* lookup failed - No MAC binding. */"); + } + union mf_subvalue sv = { .u8_val = val }; + mf_write_subfield_flow(&dst, &sv, uflow); +} + +static void execute_put_opts(const struct ovnact_put_opts *po, const char *name, struct flow *uflow, struct ovs_list *super) @@ -2216,6 +2254,16 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, execute_lookup_mac_bind(ovnact_get_LOOKUP_ND(a), dp, uflow, super); break; + case OVNACT_LOOKUP_ARP_IP: + execute_lookup_mac_bind_ip(ovnact_get_LOOKUP_ARP_IP(a), dp, uflow, + super); + break; + + case OVNACT_LOOKUP_ND_IP: + execute_lookup_mac_bind_ip(ovnact_get_LOOKUP_ND_IP(a), dp, uflow, + super); + break; + case OVNACT_PUT_DHCPV4_OPTS: execute_put_dhcp_opts(ovnact_get_PUT_DHCPV4_OPTS(a), "put_dhcp_opts", uflow, super);
lookup_arp_ip and lookup_nd_ip are added to lookup if an entry exists in MAC bindings for a given IP address, for IPv4 and IPv6 respectively. Signed-off-by: Han Zhou <hzhou@ovn.org> --- controller/lflow.c | 4 +- include/ovn/actions.h | 10 +++++ lib/actions.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/ovn.at | 50 ++++++++++++++++++++++ utilities/ovn-trace.c | 54 ++++++++++++++++++++++-- 5 files changed, 226 insertions(+), 4 deletions(-)