On Thu, Jun 11, 2020 at 12:31 AM Han Zhou <[email protected]> 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 <[email protected]>
>
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
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev