diff --git a/build-aux/extract-ofp-fields b/build-aux/extract-ofp-fields
index 3592594..3558601 100755
--- a/build-aux/extract-ofp-fields
+++ b/build-aux/extract-ofp-fields
@@ -71,7 +71,7 @@ OXM_CLASSES = {"NXM_OF_":        (0,          0x0000, 'extension'),
                "OXM_OF_":        (0,          0x8000, 'standard'),
                "OXM_OF_PKT_REG": (0,          0x8001, 'standard'),
                "ONFOXM_ET_":     (0x4f4e4600, 0xffff, 'standard'),
-
+               "ERICOXM_OF_":    (0,          0x1000, 'extension'),
                # This is the experimenter OXM class for Nicira, which is the
                # one that OVS would be using instead of NXM_OF_ and NXM_NX_
                # if OVS didn't have those grandfathered in.  It is currently
diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h
index aaeb034..9c7077f 100644
--- a/datapath/linux/compat/include/linux/openvswitch.h
+++ b/datapath/linux/compat/include/linux/openvswitch.h
@@ -484,9 +484,13 @@ struct ovs_key_arp {
 };
 
 struct ovs_key_nd {
-	__be32	nd_target[4];
-	__u8	nd_sll[ETH_ALEN];
-	__u8	nd_tll[ETH_ALEN];
+        __be32  nd_reserved;
+        __be32  nd_target[4];
+        __u8    nd_options_type;
+        struct {
+           __u8        nd_sll[ETH_ALEN];
+           __u8        nd_tll[ETH_ALEN];
+        };
 };
 
 #define OVS_CT_LABELS_LEN_32	4
diff --git a/include/openvswitch/match.h b/include/openvswitch/match.h
index e8c80dd..800c55d 100644
--- a/include/openvswitch/match.h
+++ b/include/openvswitch/match.h
@@ -68,6 +68,8 @@ void match_zero_wildcarded_fields(struct match *);
 void match_set_dp_hash(struct match *, uint32_t value);
 void match_set_dp_hash_masked(struct match *, uint32_t value, uint32_t mask);
 
+void match_set_nd_reserved(struct match *, uint32_t value);
+
 void match_set_recirc_id(struct match *, uint32_t value);
 
 void match_set_conj_id(struct match *, uint32_t value);
@@ -199,6 +201,7 @@ void match_set_nw_frag(struct match *, uint8_t nw_frag);
 void match_set_nw_frag_masked(struct match *, uint8_t nw_frag, uint8_t mask);
 void match_set_icmp_type(struct match *, uint8_t);
 void match_set_icmp_code(struct match *, uint8_t);
+void match_set_nd_options_type(struct match *, uint8_t);
 void match_set_arp_sha(struct match *, const struct eth_addr);
 void match_set_arp_sha_masked(struct match *,
                               const struct eth_addr arp_sha,
diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h
index 627c8a3..9ef23df 100644
--- a/include/openvswitch/meta-flow.h
+++ b/include/openvswitch/meta-flow.h
@@ -1796,6 +1796,34 @@ enum OVS_PACKED_ENUM mf_field_id {
      */
     MFF_ND_TLL,
 
+    /* "nd_reserved".
+     *
+     * The reserved field in IPv6 Neighbor Discovery message.
+     *
+     * Type: be32.
+     * Maskable: no.
+     * Formatting: decimal.
+     * Prerequisites: ND.
+     * Access: read/write.
+     * NXM: none.
+     * OXM: ERICOXM_OF_ICMPV6_ND_RESERVED(1) since v2.11.
+     */
+    MFF_ND_RESERVED,
+
+    /* "nd_options_type".
+     *
+     * The type of the option in IPv6 Neighbor Discovery message.
+     *
+     * Type: u8.
+     * Maskable: no.
+     * Formatting: decimal.
+     * Prerequisites: ND.
+     * Access: read/write.
+     * NXM: none.
+     * OXM: ERICOXM_OF_ICMPV6_ND_OPTIONS_TYPE(2) since v2.11.
+     */
+    MFF_ND_OPTIONS_TYPE,
+
 /* ## ---- ## */
 /* ## NSH  ## */
 /* ## ---- ## */
diff --git a/lib/flow.c b/lib/flow.c
index 128f640..2c1fe8b 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -41,6 +41,10 @@
 #include "unaligned.h"
 #include "util.h"
 #include "openvswitch/nsh.h"
+#include "openvswitch/vlog.h"
+
+VLOG_DEFINE_THIS_MODULE(flow);
+static struct vlog_rate_limit minirl = VLOG_RATE_LIMIT_INIT(1, 5);
 
 COVERAGE_DEFINE(flow_extract);
 COVERAGE_DEFINE(miniflow_malloc);
@@ -398,7 +402,7 @@ parse_ethertype(const void **datap, size_t *sizep)
 static inline bool
 parse_icmpv6(const void **datap, size_t *sizep, const struct icmp6_hdr *icmp,
              const struct in6_addr **nd_target,
-             struct eth_addr arp_buf[2])
+             struct eth_addr arp_buf[2], uint8_t *opt_type)
 {
     if (icmp->icmp6_code != 0 ||
         (icmp->icmp6_type != ND_NEIGHBOR_SOLICIT &&
@@ -408,6 +412,9 @@ parse_icmpv6(const void **datap, size_t *sizep, const struct icmp6_hdr *icmp,
 
     arp_buf[0] = eth_addr_zero;
     arp_buf[1] = eth_addr_zero;
+    opt_type[0] = 0;
+    opt_type[1] = 0;
+
     *nd_target = data_try_pull(datap, sizep, sizeof **nd_target);
     if (OVS_UNLIKELY(!*nd_target)) {
         return true;
@@ -429,12 +436,14 @@ parse_icmpv6(const void **datap, size_t *sizep, const struct icmp6_hdr *icmp,
         if (lla_opt->type == ND_OPT_SOURCE_LINKADDR && opt_len == 8) {
             if (OVS_LIKELY(eth_addr_is_zero(arp_buf[0]))) {
                 arp_buf[0] = lla_opt->mac;
+                opt_type[0] = lla_opt->type;
             } else {
                 goto invalid;
             }
         } else if (lla_opt->type == ND_OPT_TARGET_LINKADDR && opt_len == 8) {
             if (OVS_LIKELY(eth_addr_is_zero(arp_buf[1]))) {
                 arp_buf[1] = lla_opt->mac;
+                opt_type[1] = lla_opt->type;
             } else {
                 goto invalid;
             }
@@ -982,18 +991,46 @@ miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
             if (OVS_LIKELY(size >= sizeof(struct icmp6_hdr))) {
                 const struct in6_addr *nd_target;
                 struct eth_addr arp_buf[2];
-                const struct icmp6_hdr *icmp = data_pull(&data, &size,
-                                                         sizeof *icmp);
-                if (parse_icmpv6(&data, &size, icmp, &nd_target, arp_buf)) {
+                /* This will populate whether we received Option 1
+                 * or Option 2. */
+                uint8_t opt_type[2];
+                /* This holds the ND Reserved field. */
+                uint32_t *rso_flags;
+                const struct icmp6_hdr *icmp = data_pull(&data,
+                                               &size,ICMP6_HEADER_LEN);
+                rso_flags = (uint32_t *) data_pull(&data,
+                                               &size, sizeof(uint32_t));
+                if (parse_icmpv6(&data, &size, icmp,
+                                 &nd_target, arp_buf, opt_type)) {
                     if (nd_target) {
                         miniflow_push_words(mf, nd_target, nd_target,
                                             sizeof *nd_target / sizeof(uint64_t));
                     }
                     miniflow_push_macs(mf, arp_sha, arp_buf);
-                    miniflow_pad_to_64(mf, arp_tha);
+                    /* Populate options field and set the padding
+                     * accordingly. */
+                    if (opt_type[0] != 0) {
+                        miniflow_push_be16(mf, tcp_flags, htons(opt_type[0]));
+                        /* Pad to align with 64 bits.
+                         * This will zero out the pad3 field. */
+                        miniflow_pad_to_64(mf, tcp_flags);
+                    } else if (opt_type[1] != 0) {
+                        miniflow_push_be16(mf, tcp_flags, htons(opt_type[1]));
+                        /* Pad to align with 64 bits.
+                         * This will zero out the pad3 field. */
+                        miniflow_pad_to_64(mf, tcp_flags);
+                    } else {
+                        /* Pad to align with 64 bits.
+                         * This will zero out the tcp_flags & pad3 field. */
+                        miniflow_pad_to_64(mf, arp_tha);
+                    }
+
                     miniflow_push_be16(mf, tp_src, htons(icmp->icmp6_type));
                     miniflow_push_be16(mf, tp_dst, htons(icmp->icmp6_code));
                     miniflow_pad_to_64(mf, tp_dst);
+                    /* Fill ND reserved field. */
+                    miniflow_push_be32(mf, igmp_group_ip4, htonl(*rso_flags));
+                    miniflow_pad_to_64(mf, igmp_group_ip4);
                 } else {
                     /* ICMPv6 but not ND. */
                     miniflow_push_be16(mf, tp_src, htons(icmp->icmp6_type));
@@ -1840,6 +1877,9 @@ flow_wildcards_init_for_packet(struct flow_wildcards *wc,
             WC_MASK_FIELD(wc, tcp_flags);
         } else if (flow->nw_proto == IPPROTO_IGMP) {
             WC_MASK_FIELD(wc, igmp_group_ip4);
+        } else if (flow->nw_proto == IPPROTO_ICMPV6) {
+            WC_MASK_FIELD(wc, tcp_flags);
+            WC_MASK_FIELD(wc, igmp_group_ip4);
         }
     }
 }
@@ -1922,6 +1962,8 @@ flow_wc_map(const struct flow *flow, struct flowmap *map)
             FLOWMAP_SET(map, nd_target);
             FLOWMAP_SET(map, arp_sha);
             FLOWMAP_SET(map, arp_tha);
+            FLOWMAP_SET(map, tcp_flags);
+            FLOWMAP_SET(map, igmp_group_ip4);
         } else {
             FLOWMAP_SET(map, ct_nw_proto);
             FLOWMAP_SET(map, ct_ipv6_src);
@@ -2918,6 +2960,8 @@ flow_compose_l4(struct dp_packet *p, const struct flow *flow,
             struct icmp6_hdr *icmp = dp_packet_put_zeros(p, sizeof *icmp);
             icmp->icmp6_type = ntohs(flow->tp_src);
             icmp->icmp6_code = ntohs(flow->tp_dst);
+            uint32_t *reserved = &icmp->icmp6_dataun.icmp6_un_data32[0];
+            *reserved = ntohl(flow->igmp_group_ip4);
 
             if (icmp->icmp6_code == 0 &&
                 (icmp->icmp6_type == ND_NEIGHBOR_SOLICIT ||
diff --git a/lib/match.c b/lib/match.c
index a1407a8..4af7ad1 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -517,6 +517,18 @@ match_set_ct_tp_dst_masked(struct match *match, ovs_be16 port, ovs_be16 mask)
 }
 
 void
+match_set_nd_reserved (struct match *match, ovs_be32 value) {
+   match->flow.igmp_group_ip4 = value;
+   match->wc.masks.igmp_group_ip4 = OVS_BE32_MAX;
+}
+
+void
+match_set_nd_options_type(struct match *match, uint8_t option)
+{
+    match_set_tcp_flags(match, htons(option));
+}
+
+void
 match_set_ct_ipv6_src(struct match *match, const struct in6_addr *src)
 {
     match->flow.ct_ipv6_src = *src;
@@ -1688,6 +1700,10 @@ match_format(const struct match *match,
                             &wc->masks.nd_target);
         format_eth_masked(s, "nd_sll", f->arp_sha, wc->masks.arp_sha);
         format_eth_masked(s, "nd_tll", f->arp_tha, wc->masks.arp_tha);
+        format_be32_masked(s,"nd_reserved", f->igmp_group_ip4,
+                           wc->masks.igmp_group_ip4);
+        format_be16_masked(s,"nd_options_type", f->tcp_flags,
+                           wc->masks.tcp_flags);
     } else {
         format_be16_masked(s, "tp_src", f->tp_src, wc->masks.tp_src);
         format_be16_masked(s, "tp_dst", f->tp_dst, wc->masks.tp_dst);
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index b6d9e92..8059725 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -366,6 +366,11 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
         return !wc->masks.tp_dst;
+    case MFF_ND_RESERVED:
+        return !wc->masks.igmp_group_ip4;
+    case MFF_ND_OPTIONS_TYPE:
+        return !wc->masks.tcp_flags;
+
     case MFF_TCP_FLAGS:
         return !wc->masks.tcp_flags;
 
@@ -571,6 +576,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
     case MFF_ND_TARGET:
     case MFF_ND_SLL:
     case MFF_ND_TLL:
+    case MFF_ND_RESERVED:
+    case MFF_ND_OPTIONS_TYPE:
         return true;
 
     case MFF_IN_PORT_OXM:
@@ -922,6 +929,12 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
         value->u8 = ntohs(flow->tp_dst);
         break;
 
+    case MFF_ND_RESERVED:
+        value->be32 = ntohl(flow->igmp_group_ip4);
+        break;
+    case MFF_ND_OPTIONS_TYPE:
+        value->u8 = ntohs(flow->tcp_flags);
+        break;
     case MFF_ND_TARGET:
         value->ipv6 = flow->nd_target;
         break;
@@ -1255,6 +1268,12 @@ mf_set_value(const struct mf_field *mf,
         match_set_icmp_code(match, value->u8);
         break;
 
+    case MFF_ND_RESERVED:
+        match_set_nd_reserved(match, value->be32);
+        break;
+    case MFF_ND_OPTIONS_TYPE:
+        match_set_nd_options_type(match, value->u8);
+        break;
     case MFF_ND_TARGET:
         match_set_nd_target(match, &value->ipv6);
         break;
@@ -1664,6 +1683,12 @@ mf_set_flow_value(const struct mf_field *mf,
         flow->tp_dst = htons(value->u8);
         break;
 
+    case MFF_ND_RESERVED:
+        flow->igmp_group_ip4 = htonl(value->be32);
+        break;
+    case MFF_ND_OPTIONS_TYPE:
+        flow->tcp_flags = htons(value->u8);
+        break;
     case MFF_ND_TARGET:
         flow->nd_target = value->ipv6;
         break;
@@ -1823,6 +1848,8 @@ mf_is_pipeline_field(const struct mf_field *mf)
     case MFF_ND_TARGET:
     case MFF_ND_SLL:
     case MFF_ND_TLL:
+    case MFF_ND_RESERVED:
+    case MFF_ND_OPTIONS_TYPE:
     case MFF_NSH_FLAGS:
     case MFF_NSH_TTL:
     case MFF_NSH_MDTYPE:
@@ -2167,6 +2194,14 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
         match->wc.masks.tp_dst = htons(0);
         match->flow.tp_dst = htons(0);
         break;
+    case MFF_ND_RESERVED:
+        match->wc.masks.igmp_group_ip4 = htonl(0);
+        match->flow.igmp_group_ip4 = htonl(0);
+        break;
+   case MFF_ND_OPTIONS_TYPE:
+        match->wc.masks.tcp_flags = htons(0);
+        match->flow.tcp_flags = htons(0);
+        break;
 
     case MFF_TCP_FLAGS:
         match->wc.masks.tcp_flags = htons(0);
@@ -2285,6 +2320,8 @@ mf_set(const struct mf_field *mf,
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_TYPE:
     case MFF_ICMPV6_CODE:
+    case MFF_ND_RESERVED:
+    case MFF_ND_OPTIONS_TYPE:
         return OFPUTIL_P_NONE;
 
     case MFF_DP_HASH:
diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml
index 0b5c1d0..af69ade 100644
--- a/lib/meta-flow.xml
+++ b/lib/meta-flow.xml
@@ -4586,6 +4586,19 @@ r r c c c.
            title="ICMPv6 Neighbor Discovery Source Ethernet Address"/>
     <field id="MFF_ND_TLL"
            title="ICMPv6 Neighbor Discovery Target Ethernet Address"/>
+    <field id="MFF_ND_RESERVED"
+           title="ICMPv6 Neighbor Discovery Reserved Field"/>
+      <p>
+        This is used to set the R,S,O bits in Neighbor Advertisement Messages
+      </p>
+    <field id="MFF_ND_OPTIONS_TYPE"
+          title="ICMPv6 Neighbor Discovery Options Type Field"/>
+    <p>
+       A value of 1 indicates that the option is Source Link Layer.
+       A value of 2 indicates that the options is Target Link Layer.
+       See RFC 4861 for further details.
+    </p>
+
   </group>
 
   <h1>References</h1>
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 8f98032..a898567 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -990,8 +990,16 @@ nxm_put_ip(struct nxm_put_ctx *ctx,
                           ntohs(flow->tp_dst));
             }
             if (is_nd(flow, NULL)) {
+                if (match->wc.masks.igmp_group_ip4) {
+                    nxm_put_32(ctx, MFF_ND_RESERVED, oxm,
+                           ntohl(flow->igmp_group_ip4));
+                }
                 nxm_put_ipv6(ctx, MFF_ND_TARGET, oxm,
                              &flow->nd_target, &match->wc.masks.nd_target);
+                if (match->wc.masks.tcp_flags) {
+                   nxm_put_8(ctx, MFF_ND_OPTIONS_TYPE, oxm,
+                             ntohs(flow->tcp_flags));
+                }
                 if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
                     nxm_put_eth_masked(ctx, MFF_ND_SLL, oxm,
                                        flow->arp_sha, match->wc.masks.arp_sha);
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 5831d1f..77c94b8 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -239,16 +239,25 @@ odp_set_nd(struct dp_packet *packet, const struct ovs_key_nd *key,
         struct in6_addr tgt_buf;
         struct eth_addr sll_buf = eth_addr_zero;
         struct eth_addr tll_buf = eth_addr_zero;
+        uint32_t reserved = get_16aligned_be32(&ns->rso_flags);
+        uint8_t nd_options_type = lla_opt->type;
+
+        if (mask->nd_reserved) {
+            reserved = key->nd_reserved;
+        }
+        if (mask->nd_options_type) {
+            nd_options_type = key->nd_options_type;
+        }
 
         while (bytes_remain >= ND_LLA_OPT_LEN && lla_opt->len != 0) {
-            if (lla_opt->type == ND_OPT_SOURCE_LINKADDR
+            if (nd_options_type == ND_OPT_SOURCE_LINKADDR
                 && lla_opt->len == 1) {
                 sll_buf = lla_opt->mac;
                 ether_addr_copy_masked(&sll_buf, key->nd_sll, mask->nd_sll);
 
                 /* A packet can only contain one SLL or TLL option */
                 break;
-            } else if (lla_opt->type == ND_OPT_TARGET_LINKADDR
+            } else if (nd_options_type == ND_OPT_TARGET_LINKADDR
                        && lla_opt->len == 1) {
                 tll_buf = lla_opt->mac;
                 ether_addr_copy_masked(&tll_buf, key->nd_tll, mask->nd_tll);
@@ -265,7 +274,9 @@ odp_set_nd(struct dp_packet *packet, const struct ovs_key_nd *key,
                       mask_ipv6_addr(ns->target.be32, &key->nd_target,
                                      &mask->nd_target, &tgt_buf),
                       sll_buf,
-                      tll_buf);
+                      tll_buf,
+                      reserved,
+                      nd_options_type);
     }
 }
 
@@ -434,7 +445,9 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a)
             const struct ovs_key_nd *nd_key
                    = nl_attr_get_unspec(a, sizeof(struct ovs_key_nd));
             packet_set_nd(packet, &nd_key->nd_target, nd_key->nd_sll,
-                          nd_key->nd_tll);
+                          nd_key->nd_tll, nd_key->nd_reserved,
+                          nd_key->nd_options_type);
+
         }
         break;
 
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 890c71b..02351ad 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -2484,7 +2484,7 @@ const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] = {
     [OVS_KEY_ATTR_ICMP]      = { .len = sizeof(struct ovs_key_icmp) },
     [OVS_KEY_ATTR_ICMPV6]    = { .len = sizeof(struct ovs_key_icmpv6) },
     [OVS_KEY_ATTR_ARP]       = { .len = sizeof(struct ovs_key_arp) },
-    [OVS_KEY_ATTR_ND]        = { .len = sizeof(struct ovs_key_nd) },
+    [OVS_KEY_ATTR_ND]        = { .len = ATTR_LEN_VARIABLE },
     [OVS_KEY_ATTR_CT_STATE]  = { .len = 4 },
     [OVS_KEY_ATTR_CT_ZONE]   = { .len = 2 },
     [OVS_KEY_ATTR_CT_MARK]   = { .len = 4 },
@@ -4018,9 +4018,14 @@ format_odp_key_attr__(const struct nlattr *a, const struct nlattr *ma,
     case OVS_KEY_ATTR_ND: {
         const struct ovs_key_nd *mask = ma ? nl_attr_get(ma) : NULL;
         const struct ovs_key_nd *key = nl_attr_get(a);
-
+        bool first = true;
+        format_be32_masked(ds, &first, "nd_reserved", htonl(key->nd_reserved),
+                           htonl(OVS_BE32_MAX));
+        ds_put_char(ds, ',');
         format_in6_addr(ds, "target", &key->nd_target, MASK(mask, nd_target),
                         verbose);
+        format_u8u(ds,"nd_options_type", key->nd_options_type,
+                   MASK(mask,nd_options_type), verbose);
         format_eth(ds, "sll", key->nd_sll, MASK(mask, nd_sll), verbose);
         format_eth(ds, "tll", key->nd_tll, MASK(mask, nd_tll), verbose);
 
@@ -5493,7 +5498,9 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names,
     } SCAN_END(OVS_KEY_ATTR_ARP);
 
     SCAN_BEGIN("nd(", struct ovs_key_nd) {
+        SCAN_FIELD("nd_reserved=",be32,nd_reserved);
         SCAN_FIELD("target=", in6_addr, nd_target);
+        SCAN_FIELD("nd_options_type=",u8,nd_options_type);
         SCAN_FIELD("sll=", eth, nd_sll);
         SCAN_FIELD("tll=", eth, nd_tll);
     } SCAN_END(OVS_KEY_ATTR_ND);
@@ -5858,7 +5865,9 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
 
                 nd_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ND,
                                                     sizeof *nd_key);
+                nd_key->nd_reserved = ntohl(data->igmp_group_ip4);
                 nd_key->nd_target = data->nd_target;
+                nd_key->nd_options_type = ntohs(data->tcp_flags);
                 nd_key->nd_sll = data->arp_sha;
                 nd_key->nd_tll = data->arp_tha;
             }
@@ -6465,7 +6474,9 @@ parse_l2_5_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1],
                     const struct ovs_key_nd *nd_key;
 
                     nd_key = nl_attr_get(attrs[OVS_KEY_ATTR_ND]);
+                    flow->igmp_group_ip4 = htonl(nd_key->nd_reserved);
                     flow->nd_target = nd_key->nd_target;
+                    flow->tcp_flags = htons(nd_key->nd_options_type);
                     flow->arp_sha = nd_key->nd_sll;
                     flow->arp_tha = nd_key->nd_tll;
                     if (is_mask) {
@@ -7364,7 +7375,9 @@ commit_set_icmp_action(const struct flow *flow, struct flow *base_flow,
 static void
 get_nd_key(const struct flow *flow, struct ovs_key_nd *nd)
 {
+    nd->nd_reserved = ntohl(flow->igmp_group_ip4);
     nd->nd_target = flow->nd_target;
+    nd->nd_options_type = ntohs(flow->tcp_flags);
     /* nd_sll and nd_tll are stored in arp_sha and arp_tha, respectively */
     nd->nd_sll = flow->arp_sha;
     nd->nd_tll = flow->arp_tha;
@@ -7373,8 +7386,10 @@ get_nd_key(const struct flow *flow, struct ovs_key_nd *nd)
 static void
 put_nd_key(const struct ovs_key_nd *nd, struct flow *flow)
 {
+    flow->igmp_group_ip4 =htonl(nd->nd_reserved);
     flow->nd_target = nd->nd_target;
     /* nd_sll and nd_tll are stored in arp_sha and arp_tha, respectively */
+    flow->tcp_flags = htons(nd->nd_options_type);
     flow->arp_sha = nd->nd_sll;
     flow->arp_tha = nd->nd_tll;
 }
diff --git a/lib/packets.c b/lib/packets.c
index 38bfb60..81b03dd 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -1283,11 +1283,19 @@ packet_set_icmp(struct dp_packet *packet, uint8_t type, uint8_t code)
 
 void
 packet_set_nd(struct dp_packet *packet, const struct in6_addr *target,
-              const struct eth_addr sll, const struct eth_addr tll)
+              const struct eth_addr sll, const struct eth_addr tll,
+              uint32_t reserved, uint8_t nd_options_type)
 {
     struct ovs_nd_msg *ns;
     struct ovs_nd_lla_opt *opt;
     int bytes_remain = dp_packet_l4_size(packet);
+    int msg_size = bytes_remain;
+    struct ovs_16aligned_ip6_hdr * nh = dp_packet_l3(packet);
+    uint32_t pseudo_hdr_csum = 0;
+
+    if (nh) {
+        pseudo_hdr_csum = packet_csum_pseudoheader6(nh);
+    }
 
     if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) {
         return;
@@ -1296,6 +1304,7 @@ packet_set_nd(struct dp_packet *packet, const struct in6_addr *target,
     ns = dp_packet_l4(packet);
     opt = &ns->options[0];
     bytes_remain -= sizeof(*ns);
+    put_16aligned_be32(&(ns->rso_flags),reserved);
 
     if (memcmp(&ns->target, target, sizeof(ovs_be32[4]))) {
         packet_set_ipv6_addr(packet, IPPROTO_ICMPV6, ns->target.be32, target,
@@ -1303,21 +1312,17 @@ packet_set_nd(struct dp_packet *packet, const struct in6_addr *target,
     }
 
     while (bytes_remain >= ND_LLA_OPT_LEN && opt->len != 0) {
-        if (opt->type == ND_OPT_SOURCE_LINKADDR && opt->len == 1) {
+        if (nd_options_type == ND_OPT_SOURCE_LINKADDR && opt->len == 1) {
             if (!eth_addr_equals(opt->mac, sll)) {
-                ovs_be16 *csum = &(ns->icmph.icmp6_cksum);
-
-                *csum = recalc_csum48(*csum, opt->mac, sll);
+                opt->type = 1;
                 opt->mac = sll;
             }
-
             /* A packet can only contain one SLL or TLL option */
             break;
-        } else if (opt->type == ND_OPT_TARGET_LINKADDR && opt->len == 1) {
+        } else if (nd_options_type == ND_OPT_TARGET_LINKADDR
+                   && opt->len == 1) {
             if (!eth_addr_equals(opt->mac, tll)) {
-                ovs_be16 *csum = &(ns->icmph.icmp6_cksum);
-
-                *csum = recalc_csum48(*csum, opt->mac, tll);
+                opt->type = 2;
                 opt->mac = tll;
             }
 
@@ -1328,6 +1333,11 @@ packet_set_nd(struct dp_packet *packet, const struct in6_addr *target,
         opt += opt->len;
         bytes_remain -= opt->len * ND_LLA_OPT_LEN;
     }
+
+    ovs_be16 *csum_value = &(ns->icmph.icmp6_cksum);
+    *csum_value = 0;
+    *csum_value = csum_finish(csum_continue(pseudo_hdr_csum,
+                              &(ns->icmph), msg_size));
 }
 
 const char *
@@ -1505,13 +1515,12 @@ compose_nd_ns(struct dp_packet *b, const struct eth_addr eth_src,
 
     ns->icmph.icmp6_type = ND_NEIGHBOR_SOLICIT;
     ns->icmph.icmp6_code = 0;
-    put_16aligned_be32(&ns->rso_flags, htonl(0));
 
     lla_opt = &ns->options[0];
     lla_opt->type = ND_OPT_SOURCE_LINKADDR;
     lla_opt->len = 1;
 
-    packet_set_nd(b, ipv6_dst, eth_src, eth_addr_zero);
+    packet_set_nd(b, ipv6_dst, eth_src, eth_addr_zero, 0, 1);
 
     ns->icmph.icmp6_cksum = 0;
     icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
@@ -1536,13 +1545,12 @@ compose_nd_na(struct dp_packet *b,
 
     na->icmph.icmp6_type = ND_NEIGHBOR_ADVERT;
     na->icmph.icmp6_code = 0;
-    put_16aligned_be32(&na->rso_flags, rso_flags);
 
     lla_opt = &na->options[0];
     lla_opt->type = ND_OPT_TARGET_LINKADDR;
     lla_opt->len = 1;
 
-    packet_set_nd(b, ipv6_src, eth_addr_zero, eth_src);
+    packet_set_nd(b, ipv6_src, eth_addr_zero, eth_src, rso_flags, 2);
 
     na->icmph.icmp6_cksum = 0;
     icmp_csum = packet_csum_pseudoheader6(dp_packet_l3(b));
diff --git a/lib/packets.h b/lib/packets.h
index 09a0ac3..18590f3 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -1542,7 +1542,8 @@ void packet_set_udp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);
 void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst);
 void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code);
 void packet_set_nd(struct dp_packet *, const struct in6_addr *target,
-                   const struct eth_addr sll, const struct eth_addr tll);
+                   const struct eth_addr sll, const struct eth_addr tll,
+                   const ovs_be32 reserved, const uint8_t nd_options_type);
 
 void packet_format_tcp_flags(struct ds *, uint16_t);
 const char *packet_tcp_flag_to_string(uint32_t flag);
diff --git a/tests/odp.at b/tests/odp.at
index aad89e8..90df12b 100644
--- a/tests/odp.at
+++ b/tests/odp.at
@@ -19,9 +19,9 @@ in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=6,tclass=0,hlimit=128,frag=no),tcp(src=80,dst=8080)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=17,tclass=0,hlimit=128,frag=no),udp(src=6630,dst=22)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=1,code=2)
-in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(target=::3,sll=00:05:06:07:08:09,tll=00:0a:0b:0c:0d:0e)
+in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(nd_reserved=0x0,target=::3,nd_options_type=0,sll=00:05:06:07:08:09,tll=00:0a:0b:0c:0d:0e)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0806),arp(sip=1.2.3.4,tip=5.6.7.8,op=1,sha=00:0f:10:11:12:13,tha=00:14:15:16:17:18)
-in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(target=::3,sll=00:05:06:07:08:09,tll=00:0a:0b:0c:0d:0e)
+in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(nd_reserved=0x0,target=::3,nd_options_type=0,sll=00:05:06:07:08:09,tll=00:0a:0b:0c:0d:0e)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x8847),mpls(label=100,tc=3,ttl=64,bos=1)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x8847),mpls(label=100,tc=7,ttl=100,bos=1)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x8847),mpls(label=100,tc=7,ttl=100,bos=0)
@@ -124,12 +124,12 @@ in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=6,tclass=0,hlimit=128,frag=no),tcp(src=80/0xff00,dst=8080/0xff)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=17,tclass=0,hlimit=128,frag=no),udp(src=6630/0xff00,dst=22/0xff)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=1/0xf0,code=2)
-in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=135,code=0),nd(target=::3/::250)
-in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=135,code=0),nd(target=::3/::250,sll=00:05:06:07:08:09/ff:ff:ff:ff:ff:00)
-in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(target=::3/::250,tll=00:0a:0b:0c:0d:0e/ff:ff:ff:ff:ff:00)
-in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(target=::3/::250,sll=00:05:06:07:08:09/ff:ff:ff:ff:ff:00,tll=00:0a:0b:0c:0d:0e/ff:ff:ff:ff:ff:00)
+in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=135,code=0),nd(nd_reserved=0x0,target=::3/::250,nd_options_type=0)
+in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=135,code=0),nd(nd_reserved=0x0,target=::3/::250,nd_options_type=0,sll=00:05:06:07:08:09/ff:ff:ff:ff:ff:00)
+in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(nd_reserved=0x0,target=::3/::250,nd_options_type=0,tll=00:0a:0b:0c:0d:0e/ff:ff:ff:ff:ff:00)
+in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(nd_reserved=0x0,target=::3/::250,nd_options_type=0,sll=00:05:06:07:08:09/ff:ff:ff:ff:ff:00,tll=00:0a:0b:0c:0d:0e/ff:ff:ff:ff:ff:00)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0806),arp(sip=1.2.3.4/255.255.255.250,tip=5.6.7.8/255.255.255.250,op=1/0xf0,sha=00:0f:10:11:12:13/ff:ff:ff:ff:ff:00,tha=00:14:15:16:17:18/ff:ff:ff:ff:ff:00)
-skb_mark(0x1234/0xfff0),in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(target=::3,sll=00:05:06:07:08:09,tll=00:0a:0b:0c:0d:0e)
+skb_mark(0x1234/0xfff0),in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(nd_reserved=0x0,target=::3,nd_options_type=0,sll=00:05:06:07:08:09,tll=00:0a:0b:0c:0d:0e)
 ])
 
 (echo '# Valid forms without tun_id or VLAN header.'
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 362c58d..9790dbc 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -269,7 +269,7 @@ AT_CHECK([ovs-ofctl -O OpenFlow12 add-flows br0 flows.txt])
 AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,icmp6,ipv6_src=fe80::1,ipv6_dst=fe80::2,nw_tos=0,nw_ttl=128,icmpv6_type=135,nd_target=fe80::2020,nd_sll=66:55:44:33:22:11'], [0], [stdout])
 AT_CHECK([tail -4 stdout], [0],
   [Megaflow: recirc_id=0,eth,icmp6,in_port=1,nw_frag=no,icmp_type=0x87/0xff,icmp_code=0x0/0xff,nd_target=fe80::2020,nd_sll=66:55:44:33:22:11
-Datapath actions: 10,set(nd(target=fe80::4,sll=cc:cc:cc:cc:cc:cc)),11,set(nd(target=fe80::3,sll=aa:aa:aa:aa:aa:aa)),13
+Datapath actions: 10,set(nd(nd_reserved=0x0,target=fe80::4,sll=cc:cc:cc:cc:cc:cc)),11,set(nd(nd_reserved=0x0,target=fe80::3,sll=aa:aa:aa:aa:aa:aa)),13
 This flow is handled by the userspace slow path because it:
   - Uses action(s) not supported by datapath.
 ])
@@ -9152,7 +9152,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
 
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via no_match) data_len=86 (unbuffered)
-icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::260:97ff:fe07:69ea,nd_sll=00:00:86:05:80:da,nd_tll=00:00:00:00:00:00 icmp6_csum:68bd
+icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::260:97ff:fe07:69ea,nd_sll=00:00:86:05:80:da,nd_tll=00:00:00:00:00:00,nd_reserved=0,nd_options_type=1 icmp6_csum:68bd
 ])
 
 OVS_VSWITCHD_STOP
@@ -9203,7 +9203,7 @@ OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
 
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via action) data_len=86 (unbuffered)
-icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::1,nd_sll=32:21:14:86:11:74,nd_tll=00:00:00:00:00:00 icmp6_csum:19d3
+icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::1,nd_sll=32:21:14:86:11:74,nd_tll=00:00:00:00:00:00,nd_reserved=0,nd_options_type=1 icmp6_csum:19d3
 ])
 
 OVS_VSWITCHD_STOP
@@ -9764,7 +9764,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
 
 AT_CHECK([cat ofctl_monitor.log], [0], [dnl
 NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 ct_state=inv|trk,ipv6,in_port=2 (via action) data_len=86 (unbuffered)
-icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::260:97ff:fe07:69ea,nd_sll=00:00:86:05:80:da,nd_tll=00:00:00:00:00:00 icmp6_csum:68bd
+icmp6,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::260:97ff:fe07:69ea,nd_sll=00:00:86:05:80:da,nd_tll=00:00:00:00:00:00,nd_reserved=0,nd_options_type=1 icmp6_csum:68bd
 ])
 
 OVS_VSWITCHD_STOP
diff --git a/tests/ofproto.at b/tests/ofproto.at
index 9819bc5..6a876c0 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -2456,7 +2456,7 @@ head_table () {
         actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue
         supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_erspan_idx tun_erspan_ver tun_erspan_dir tun_erspan_hwid tun_metadata0 dnl
 tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata58 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 dnl
-metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll nsh_flags nsh_spi nsh_si nsh_c1 nsh_c2 nsh_c3 nsh_c4 nsh_ttl
+metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12 reg13 reg14 reg15 xreg0 xreg1 xreg2 xreg3 xreg4 xreg5 xreg6 xreg7 xxreg0 xxreg1 xxreg2 xxreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll nd_reserved nd_options_type nsh_flags nsh_spi nsh_si nsh_c1 nsh_c2 nsh_c3 nsh_c4 nsh_ttl
     matching:
       dp_hash: arbitrary mask
       recirc_id: exact match or wildcard
@@ -2622,6 +2622,8 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4
       nd_target: arbitrary mask
       nd_sll: arbitrary mask
       nd_tll: arbitrary mask
+      nd_reserved: exact match or wildcard
+      nd_options_type: exact match or wildcard
       nsh_flags: arbitrary mask
       nsh_mdtype: exact match or wildcard
       nsh_np: exact match or wildcard
