From patchwork Fri May 27 02:32:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zong Kai LI X-Patchwork-Id: 626982 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (archives.nicira.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 3rGBQN0mPfz9snm for ; Fri, 27 May 2016 13:31:55 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=zB618Pu+; dkim-atps=neutral Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id C116910AB6; Thu, 26 May 2016 20:31:53 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v3.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 5248E10AB5 for ; Thu, 26 May 2016 20:31:52 -0700 (PDT) Received: from bar6.cudamail.com (localhost [127.0.0.1]) by mx3v3.cudamail.com (Postfix) with ESMTPS id A27131624AC for ; Thu, 26 May 2016 21:31:51 -0600 (MDT) X-ASG-Debug-ID: 1464319910-0b323715aab5c70001-byXFYA Received: from mx1-pf1.cudamail.com ([192.168.24.1]) by bar6.cudamail.com with ESMTP id vzNALwBzh466cpED (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 26 May 2016 21:31:50 -0600 (MDT) X-Barracuda-Envelope-From: zealokii@gmail.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.1 Received: from unknown (HELO mail-oi0-f66.google.com) (209.85.218.66) by mx1-pf1.cudamail.com with ESMTPS (AES128-SHA encrypted); 27 May 2016 03:31:49 -0000 Received-SPF: pass (mx1-pf1.cudamail.com: SPF record at _netblocks.google.com designates 209.85.218.66 as permitted sender) X-Barracuda-Apparent-Source-IP: 209.85.218.66 X-Barracuda-RBL-IP: 209.85.218.66 Received: by mail-oi0-f66.google.com with SMTP id h125so8489086oib.2 for ; Thu, 26 May 2016 20:31:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=KY2RdOMvTpkVCxFFhA+XhCzzk/XLhWuL1qZJJAhxrrI=; b=zB618Pu+YPTb6/kunb71KDP+RJCtGAp1WQu0p/YguF/GVP/knNbdDroXMmYmFBKcoi QWQpW667fldAirNdyNfyBLp6VIeyc194CecFgz2cboOEcOJO7oGFdhvgVpFWUYDT3sbV P5Ji86S8/z+mcq/wkVk9EQxEqQ5AlyCPn/ze1EM/6Ygny0b3/DHpupBZR2ldRt3o13K4 o7LewuXPV//wXXj+njrH296WzidgetQWvng3KZae3YShM3LP+tCOV2kGDtcqNC+WiEY5 PcyQQTpP22RhMtSSGvW9rQVq+gMVCnthj16+ciHFRmFFwQuX6bcRyastPZEuOmz7eBs7 1FRQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=KY2RdOMvTpkVCxFFhA+XhCzzk/XLhWuL1qZJJAhxrrI=; b=bp5z4QWqpKeReeRacTmnPTNH/bOU0vMEY3q9Dbm5kpbxvhsECwqoYvDcQNNHgEhKtu HdO7mAX74vAwcdA4BucJvsnkLUCqsfSAAfILwGRfc3OqcrNuOer2r3Lx74oBCvEfleMD NdxoMB9yNLUrECfu+LUD5uelJpO454OJOLd3Ck2C30nwY5xsBInxR9hh+EmZ8iHUpqQH 5C52ZB5+2Wkr3n04BvzkHFLS07ToGVKi4jLiGBZvK84CLqpK0vWEQLqG29iVqRQqdOXJ +337qjQdHBerQyrZE49TtaGXhZ5IeA9gq/TVnVG5gcZVrlWAscJjt6k6pzPTU5GBoOIs Lgjw== X-Gm-Message-State: ALyK8tI8qX6KFv6VXEzwd+a4UpjuRN8uJDrpe4SWJmZNHnUZihxG/JtmZ2prj1KcYVEQjQ== X-Received: by 10.202.225.5 with SMTP id y5mr8203619oig.187.1464316384052; Thu, 26 May 2016 19:33:04 -0700 (PDT) Received: from localhost.localdomain ([106.38.0.70]) by smtp.gmail.com with ESMTPSA id 90sm8038096otx.14.2016.05.26.19.33.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 26 May 2016 19:33:03 -0700 (PDT) X-CudaMail-Envelope-Sender: zealokii@gmail.com From: Zong Kai LI To: dev@openvswitch.org X-CudaMail-MID: CM-E1-525096880 X-CudaMail-DTE: 052616 X-CudaMail-Originating-IP: 209.85.218.66 Date: Fri, 27 May 2016 10:32:56 +0800 X-ASG-Orig-Subj: [##CM-E1-525096880##][PATCH] WIP OVN ND for Logical_Port Message-Id: <1464316376-13278-1-git-send-email-zealokii@gmail.com> X-Mailer: git-send-email 1.9.1 X-Barracuda-Connect: UNKNOWN[192.168.24.1] X-Barracuda-Start-Time: 1464319910 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-Spam-Score: 1.10 X-Barracuda-Spam-Status: No, SCORE=1.10 using global scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_RULE7568M, BSF_SC5_MJ1963, DKIM_SIGNED, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.29935 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.50 BSF_RULE7568M Custom Rule 7568M 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Cc: lzklibj Subject: [ovs-dev] [PATCH] WIP OVN ND for Logical_Port X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" From: lzklibj This patch tries to implement ND for Logical_Port in OVN. Signed-off-by: lzklibj --- lib/packets.c | 2 +- lib/packets.h | 3 + ovn/controller/pinctrl.c | 156 +++++++++++++++++++++++++++++++++++++++-------- ovn/lib/actions.c | 50 +++++++++++++++ ovn/lib/actions.h | 6 ++ ovn/lib/expr.c | 47 +------------- ovn/lib/expr.h | 43 +++++++++++++ ovn/northd/ovn-northd.c | 30 ++++++++- 8 files changed, 266 insertions(+), 71 deletions(-) diff --git a/lib/packets.c b/lib/packets.c index 6a55d6f..ad7c389 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -1301,7 +1301,7 @@ compose_arp__(struct dp_packet *b) /* This function expect packet with ethernet header with correct * l3 pointer set. */ -static void * +void * compose_ipv6(struct dp_packet *packet, uint8_t proto, const ovs_be32 src[4], const ovs_be32 dst[4], uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size) diff --git a/lib/packets.h b/lib/packets.h index 5945940..82d793c 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -274,6 +274,9 @@ static inline uint32_t hash_mac(const struct eth_addr ea, bool eth_addr_is_reserved(const struct eth_addr); bool eth_addr_from_string(const char *, struct eth_addr *); +void *compose_ipv6(struct dp_packet *packet, uint8_t proto, const ovs_be32 src[4], + const ovs_be32 dst[4], uint8_t key_tc, ovs_be32 key_fl, + uint8_t key_hl, int size); void compose_rarp(struct dp_packet *, const struct eth_addr); void eth_push_vlan(struct dp_packet *, ovs_be16 tpid, ovs_be16 tci); diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index bc57c40..5265207 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -14,6 +14,7 @@ */ #include +#include #include "pinctrl.h" @@ -23,6 +24,8 @@ #include "flow.h" #include "lport.h" #include "ovn-controller.h" +#include "lib/csum.h" +#include "lib/packets.h" #include "lib/sset.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/ofp-msgs.h" @@ -64,6 +67,14 @@ static void send_garp_run(const struct ovsrec_bridge *, const char *chassis_id, const struct lport_index *lports, struct hmap *local_datapaths); +static void pinctrl_handle_nd(const struct flow *ip_flow, + const struct match *md, + struct ofpbuf *userdata); +void compose_na(struct dp_packet *, + const struct eth_addr eth_src, const struct eth_addr eth_dst, + const struct in6_addr *, const struct in6_addr *); +void reload_metadata(struct ofpbuf *ofpacts, + const struct match *md); COVERAGE_DEFINE(pinctrl_drop_put_arp); @@ -153,31 +164,7 @@ pinctrl_handle_arp(const struct flow *ip_flow, const struct match *md, struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); enum ofp_version version = rconn_get_version(swconn); - enum mf_field_id md_fields[] = { -#if FLOW_N_REGS == 8 - MFF_REG0, - MFF_REG1, - MFF_REG2, - MFF_REG3, - MFF_REG4, - MFF_REG5, - MFF_REG6, - MFF_REG7, -#else -#error -#endif - MFF_METADATA, - }; - for (size_t i = 0; i < ARRAY_SIZE(md_fields); i++) { - const struct mf_field *field = mf_from_id(md_fields[i]); - if (!mf_is_all_wild(field, &md->wc)) { - struct ofpact_set_field *sf = ofpact_put_SET_FIELD(&ofpacts); - sf->field = field; - sf->flow_has_vlan = false; - mf_get_value(field, &md->flow, &sf->value); - memset(&sf->mask, 0xff, field->n_bytes); - } - } + reload_metadata(&ofpacts, md); enum ofperr error = ofpacts_pull_openflow_actions(userdata, userdata->size, version, &ofpacts); if (error) { @@ -242,6 +229,10 @@ process_packet_in(const struct ofp_header *msg) pinctrl_handle_put_arp(&pin.flow_metadata.flow, &headers); break; + case ACTION_OPCODE_ND: + pinctrl_handle_nd(&headers, &pin.flow_metadata, &userdata); + break; + default: VLOG_WARN_RL(&rl, "unrecognized packet-in opcode %"PRIu32, ntohl(ah->opcode)); @@ -734,3 +725,118 @@ send_garp_run(const struct ovsrec_bridge *br_int, const char *chassis_id, sset_destroy(&localnet_vifs); simap_destroy(&localnet_ofports); } + +void +compose_na(struct dp_packet *b, + const struct eth_addr eth_src, const struct eth_addr eth_dst, + const struct in6_addr *ipv6_src, const struct in6_addr *ipv6_dst) +{ + struct ovs_nd_msg *na; + struct ovs_nd_opt *nd_opt; + uint32_t icmp_csum; + + eth_compose(b, eth_dst, eth_src, ETH_TYPE_IPV6, IPV6_HEADER_LEN); + na = compose_ipv6(b, IPPROTO_ICMPV6, + ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr), + ALIGNED_CAST(ovs_be32 *, ipv6_dst->s6_addr), + 0, 0, 255, + ND_MSG_LEN + ND_OPT_LEN); + + na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT; + na->icmph.icmp6_code = 0; + //TODO(lizk): RSO ? + na->rco_flags.hi = (ovs_be16)0x60; + + nd_opt = &na->options[0]; + nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; + nd_opt->nd_opt_len = 1; + + packet_set_nd(b, ALIGNED_CAST(ovs_be32 *, ipv6_src->s6_addr), + eth_addr_zero, eth_src); + na->icmph.icmp6_cksum = 0; + icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b)); + na->icmph.icmp6_cksum = csum_finish(csum_continue(icmp_csum, na, + ND_MSG_LEN + ND_OPT_LEN)); +} + +void reload_metadata(struct ofpbuf *ofpacts, const struct match *md) +{ + enum mf_field_id md_fields[] = { +#if FLOW_N_REGS == 8 + MFF_REG0, + MFF_REG1, + MFF_REG2, + MFF_REG3, + MFF_REG4, + MFF_REG5, + MFF_REG6, + MFF_REG7, +#else +#error +#endif + MFF_METADATA, + }; + for (size_t i = 0; i < ARRAY_SIZE(md_fields); i++) { + const struct mf_field *field = mf_from_id(md_fields[i]); + if (!mf_is_all_wild(field, &md->wc)) { + struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ofpacts); + sf->field = field; + sf->flow_has_vlan = false; + mf_get_value(field, &md->flow, &sf->value); + memset(&sf->mask, 0xff, field->n_bytes); + } + } +} + +static void +pinctrl_handle_nd(const struct flow *ip_flow, + const struct match *md, + struct ofpbuf *userdata) +{ + enum ofp_version version = rconn_get_version(swconn); + enum ofputil_protocol proto = ofputil_protocol_from_ofp_version(version); + + const struct eth_addr *dl_reply = ofpbuf_try_pull(userdata, + sizeof *dl_reply); + if (!dl_reply) { + goto exit; + } + + //TODO(lizk): Validate the NS packet. + + // Frame the NA packet. + uint64_t packet_stub[128 / 8]; + struct dp_packet packet; + dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); + compose_na(&packet, + *dl_reply, ip_flow->dl_src, + &(ip_flow->nd_target), &(ip_flow->ipv6_src)); + + uint64_t ofpacts_stub[4096 / 8]; + struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); + reload_metadata(&ofpacts, md); + + enum ofperr error = ofpacts_pull_openflow_actions(userdata, userdata->size, + version, &ofpacts); + if (error) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, "failed to parse actions for put_nd_tll (%s)", + ofperr_to_string(error)); + goto exit; + } + + struct ofputil_packet_out po = { + .packet = dp_packet_data(&packet), + .packet_len = dp_packet_size(&packet), + .buffer_id = UINT32_MAX, + .in_port = OFPP_CONTROLLER, + .ofpacts = ofpacts.data, + .ofpacts_len = ofpacts.size, + }; + + queue_msg(ofputil_encode_packet_out(&po, proto)); + +exit: + dp_packet_uninit(&packet); + ofpbuf_uninit(&ofpacts); +} diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c index 5f0bf19..2fce543 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -442,6 +442,54 @@ emit_ct(struct action_context *ctx, bool recirc_next, bool commit) add_prerequisite(ctx, "ip"); } +static void +parse_put_nd_action(struct action_context *ctx) +{ + if (!lexer_match(ctx->lexer, LEX_T_LPAREN)) { + action_syntax_error(ctx, "expecting `('"); + return; + } + + struct expr_constant_set cs; + struct expr_context expr_ctx = { + .lexer = ctx->lexer, + .symtab = NULL, + }; + if (!parse_constant_set(&expr_ctx, &cs)) { + action_syntax_error(ctx, "expecting NA mac"); + return; + } + if (!lexer_match(ctx->lexer, LEX_T_SEMICOLON)) { + action_syntax_error(ctx, "expecting ';'"); + return; + } + + struct ofpbuf *outer_ofpacts = ctx->ofpacts; + uint64_t inner_ofpacts_stub[1024 / 8]; + struct ofpbuf inner_ofpacts = OFPBUF_STUB_INITIALIZER(inner_ofpacts_stub); + ctx->ofpacts = &inner_ofpacts; + + /* Parse inner actions. */ + while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) { + if (!parse_action(ctx)) { + break; + } + } + + ctx->ofpacts = outer_ofpacts; + + /* controller. */ + size_t oc_offset = start_controller_op(ctx->ofpacts, ACTION_OPCODE_ND); + ofpbuf_put(ctx->ofpacts, &cs.values[0].value.mac, sizeof(struct eth_addr)); + ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size, + ctx->ofpacts, OFP13_VERSION); + finish_controller_op(ctx->ofpacts, oc_offset); + + /* Free memory. */ + expr_constant_set_destroy(&cs); + ofpbuf_uninit(&inner_ofpacts); +} + static bool parse_action(struct action_context *ctx) { @@ -475,6 +523,8 @@ parse_action(struct action_context *ctx) parse_get_arp_action(ctx); } else if (lexer_match_id(ctx->lexer, "put_arp")) { parse_put_arp_action(ctx); + } else if (lexer_match_id(ctx->lexer, "put_nd_tll")) { + parse_put_nd_action(ctx); } else { action_syntax_error(ctx, "expecting action"); } diff --git a/ovn/lib/actions.h b/ovn/lib/actions.h index 29af06f..c5cc84c 100644 --- a/ovn/lib/actions.h +++ b/ovn/lib/actions.h @@ -44,6 +44,12 @@ enum action_opcode { * MFF_ETH_SRC = mac */ ACTION_OPCODE_PUT_ARP, + + /* "put_nd_tll(mac; ...actions... )". + * + * The actions, in OpenFlow 1.3 format, follow the action_header. + */ + ACTION_OPCODE_ND }; /* Header. */ diff --git a/ovn/lib/expr.c b/ovn/lib/expr.c index f274ab4..b89b207 100644 --- a/ovn/lib/expr.c +++ b/ovn/lib/expr.c @@ -405,39 +405,6 @@ expr_print(const struct expr *e) /* Parsing. */ -/* Type of a "union expr_constant" or "struct expr_constant_set". */ -enum expr_constant_type { - EXPR_C_INTEGER, - EXPR_C_STRING -}; - -/* A string or integer constant (one must know which from context). */ -union expr_constant { - /* Integer constant. - * - * The width of a constant isn't always clear, e.g. if you write "1", - * there's no way to tell whether you mean for that to be a 1-bit constant - * or a 128-bit constant or somewhere in between. */ - struct { - union mf_subvalue value; - union mf_subvalue mask; /* Only initialized if 'masked'. */ - bool masked; - - enum lex_format format; /* From the constant's lex_token. */ - }; - - /* Null-terminated string constant. */ - char *string; -}; - -/* A collection of "union expr_constant"s of the same type. */ -struct expr_constant_set { - union expr_constant *values; /* Constants. */ - size_t n_values; /* Number of constants. */ - enum expr_constant_type type; /* Type of the constants. */ - bool in_curlies; /* Whether the constants were in {}. */ -}; - /* A reference to a symbol or a subfield of a symbol. * * For string fields, ofs and n_bits are 0. */ @@ -447,17 +414,9 @@ struct expr_field { int n_bits; /* Number of bits. */ }; -/* Context maintained during expr_parse(). */ -struct expr_context { - struct lexer *lexer; /* Lexer for pulling more tokens. */ - const struct shash *symtab; /* Symbol table. */ - char *error; /* Error, if any, otherwise NULL. */ - bool not; /* True inside odd number of NOT operators. */ -}; - struct expr *expr_parse__(struct expr_context *); static void expr_not(struct expr *); -static void expr_constant_set_destroy(struct expr_constant_set *); +void expr_constant_set_destroy(struct expr_constant_set *); static bool parse_field(struct expr_context *, struct expr_field *); static bool @@ -812,7 +771,7 @@ parse_constant(struct expr_context *ctx, struct expr_constant_set *cs, * which the caller need not have initialized. Returns true on success, in * which case the caller owns 'cs', false on failure, in which case 'cs' is * indeterminate. */ -static bool +bool parse_constant_set(struct expr_context *ctx, struct expr_constant_set *cs) { size_t allocated_values = 0; @@ -838,7 +797,7 @@ parse_constant_set(struct expr_context *ctx, struct expr_constant_set *cs) return ok; } -static void +void expr_constant_set_destroy(struct expr_constant_set *cs) { if (cs) { diff --git a/ovn/lib/expr.h b/ovn/lib/expr.h index 1327789..2742d2a 100644 --- a/ovn/lib/expr.h +++ b/ovn/lib/expr.h @@ -391,4 +391,47 @@ char *expr_parse_field(struct lexer *, int n_bits, bool rw, const struct shash *symtab, struct mf_subfield *, struct expr **prereqsp); +/* Context maintained during expr_parse(). */ +struct expr_context { + struct lexer *lexer; /* Lexer for pulling more tokens. */ + const struct shash *symtab; /* Symbol table. */ + char *error; /* Error, if any, otherwise NULL. */ + bool not; /* True inside odd number of NOT operators. */ +}; + +/* Type of a "union expr_constant" or "struct expr_constant_set". */ +enum expr_constant_type { + EXPR_C_INTEGER, + EXPR_C_STRING +}; + +/* A string or integer constant (one must know which from context). */ +union expr_constant { + /* Integer constant. + * + * The width of a constant isn't always clear, e.g. if you write "1", + * there's no way to tell whether you mean for that to be a 1-bit constant + * or a 128-bit constant or somewhere in between. */ + struct { + union mf_subvalue value; + union mf_subvalue mask; /* Only initialized if 'masked'. */ + bool masked; + + enum lex_format format; /* From the constant's lex_token. */ + }; + + /* Null-terminated string constant. */ + char *string; +}; + +/* A collection of "union expr_constant"s of the same type. */ +struct expr_constant_set { + union expr_constant *values; /* Constants. */ + size_t n_values; /* Number of constants. */ + enum expr_constant_type type; /* Type of the constants. */ + bool in_curlies; /* Whether the constants were in {}. */ +}; + +bool parse_constant_set(struct expr_context *ctx, struct expr_constant_set *cs); +void expr_constant_set_destroy(struct expr_constant_set *cs); #endif /* ovn/expr.h */ diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 44e9430..38796a1 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -1381,6 +1381,15 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows, struct hmap *ports) bool ingress = !strcmp(acl->direction, "from-lport") ? true :false; enum ovn_stage stage = ingress ? S_SWITCH_IN_ACL : S_SWITCH_OUT_ACL; + //NOTE(lizk) + /* why it's allow-related for icmp6 ? */ + if (strstr(acl->match, "ip6 && icmp6")) { + ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, + acl->priority + OVN_ACL_PRI_OFFSET, + acl->match, "output;"); + continue; + } + if (!strcmp(acl->action, "allow")) { /* If there are any stateful flows, we must even commit "allow" * actions. This is because, while the initiater's @@ -1531,7 +1540,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, for (size_t i = 0; i < op->nbs->n_addresses; i++) { struct lport_addresses laddrs; if (!extract_lport_addresses(op->nbs->addresses[i], &laddrs, - false)) { + true)) { continue; } for (size_t j = 0; j < laddrs.n_ipv4_addrs; j++) { @@ -1557,8 +1566,27 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, free(match); free(actions); } + char ip6_str[INET6_ADDRSTRLEN + 1]; + for (size_t j = 0; j < laddrs.n_ipv6_addrs; j++) { + ipv6_string_mapped(ip6_str, &(laddrs.ipv6_addrs[i].addr)); + + struct ds match = DS_EMPTY_INITIALIZER; + ds_put_cstr(&match, "ip6 && nd && icmp6.type == 135 && nd.target == "); + ds_put_format(&match, "%s", ip6_str); + struct ds actions = DS_EMPTY_INITIALIZER; + ds_put_cstr(&actions, "put_nd_tll("); + ds_put_format(&actions, ETH_ADDR_FMT, ETH_ADDR_ARGS(laddrs.ea)); + ds_put_cstr(&actions, ";outport = inport; inport = \"\";output;);"); + + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_RSP, 50, + ds_cstr(&match), ds_cstr(&actions)); + + ds_destroy(&actions); + ds_destroy(&match); + } free(laddrs.ipv4_addrs); + free(laddrs.ipv6_addrs); } }