Complete the IGMP protocol support by making IGMP fields (type, code,
and group) matchable via OpenFlow by the way of new Nicira extensions.

The new fields are: 8-bit NXM_NX_IGMP_TYPE (111), 8-bit
NXM_NX_IGMP_CODE (112), and 32-bit NXM_NX_IGMP_GROUP (113).

VMware-BZ: #1558992
Signed-off-by: Jarno Rajahalme <ja...@ovn.org>
---
 build-aux/extract-ofp-fields |  1 +
 lib/match.c                  | 15 ++++++++++++++
 lib/match.h                  |  3 +++
 lib/meta-flow.c              | 45 +++++++++++++++++++++++++++++++++++++++++-
 lib/meta-flow.h              | 47 ++++++++++++++++++++++++++++++++++++++++++++
 lib/nx-match.c               |  9 +++++++++
 tests/ofproto.at             |  3 +++
 tests/ovs-ofctl.at           | 38 +++++++++++++++++++++++++++++++++++
 8 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/build-aux/extract-ofp-fields b/build-aux/extract-ofp-fields
index 8d43e4b..d1f5825 100755
--- a/build-aux/extract-ofp-fields
+++ b/build-aux/extract-ofp-fields
@@ -46,6 +46,7 @@ PREREQS = {"none": "MFP_NONE",
            "SCTP": "MFP_SCTP",
            "ICMPv4": "MFP_ICMPV4",
            "ICMPv6": "MFP_ICMPV6",
+           "IGMP": "MFP_IGMP",
            "ND": "MFP_ND",
            "ND solicit": "MFP_ND_SOLICIT",
            "ND advert": "MFP_ND_ADVERT"}
diff --git a/lib/match.c b/lib/match.c
index 95d34bc..a725737 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -725,6 +725,21 @@ match_set_icmp_code(struct match *match, uint8_t icmp_code)
 }
 
 void
+match_set_igmp_group(struct match *match, ovs_be32 igmp_group)
+{
+    match->flow.igmp_group_ip4 = igmp_group;
+    match->wc.masks.igmp_group_ip4 = OVS_BE32_MAX;
+}
+
+void
+match_set_igmp_group_masked(struct match *match, ovs_be32 igmp_group,
+                            ovs_be32 mask)
+{
+    match->flow.igmp_group_ip4 = igmp_group & mask;
+    match->wc.masks.igmp_group_ip4 = mask;
+}
+
+void
 match_set_arp_sha(struct match *match, const struct eth_addr sha)
 {
     match->flow.arp_sha = sha;
diff --git a/lib/match.h b/lib/match.h
index 650a203..66a3664 100644
--- a/lib/match.h
+++ b/lib/match.h
@@ -125,6 +125,9 @@ void match_set_mpls_lse(struct match *, int idx, ovs_be32 
lse);
 void match_set_tp_src_masked(struct match *, ovs_be16 port, ovs_be16 mask);
 void match_set_tp_dst(struct match *, ovs_be16);
 void match_set_tp_dst_masked(struct match *, ovs_be16 port, ovs_be16 mask);
+void match_set_igmp_group(struct match *, ovs_be32);
+void match_set_igmp_group_masked(struct match *, ovs_be32 igmp_group,
+                                 ovs_be32 mask);
 void match_set_tcp_flags(struct match *, ovs_be16);
 void match_set_tcp_flags_masked(struct match *, ovs_be16 flags, ovs_be16 mask);
 void match_set_nw_proto(struct match *, uint8_t);
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index 6bd0b99..04f75e2 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -306,15 +306,19 @@ mf_is_all_wild(const struct mf_field *mf, const struct 
flow_wildcards *wc)
     case MFF_SCTP_SRC:
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV6_TYPE:
+    case MFF_IGMP_TYPE:
         return !wc->masks.tp_src;
     case MFF_TCP_DST:
     case MFF_UDP_DST:
     case MFF_SCTP_DST:
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
+    case MFF_IGMP_CODE:
         return !wc->masks.tp_dst;
     case MFF_TCP_FLAGS:
         return !wc->masks.tcp_flags;
+    case MFF_IGMP_GROUP:
+        return !wc->masks.igmp_group_ip4;
 
     case MFF_N_IDS:
     default:
@@ -387,7 +391,9 @@ mf_are_prereqs_ok(const struct mf_field *mf, const struct 
flow *flow)
         return is_icmpv4(flow);
     case MFP_ICMPV6:
         return is_icmpv6(flow);
-
+    case MFP_IGMP:
+        return is_igmp(flow);
+        
     case MFP_ND:
         return (is_icmpv6(flow)
                 && flow->tp_dst == htons(0)
@@ -426,6 +432,7 @@ mf_mask_field_and_prereqs(const struct mf_field *mf, struct 
flow_wildcards *wc)
     case MFP_SCTP:
     case MFP_ICMPV4:
     case MFP_ICMPV6:
+    case MFP_IGMP:
         /* nw_frag always unwildcarded. */
         WC_MASK_FIELD(wc, nw_proto);
         /* Fall through. */
@@ -462,6 +469,7 @@ mf_bitmap_set_field_and_prereqs(const struct mf_field *mf, 
struct mf_bitmap *bm)
     case MFP_SCTP:
     case MFP_ICMPV4:
     case MFP_ICMPV6:
+    case MFP_IGMP:
         /* nw_frag always unwildcarded. */
         bitmap_set1(bm->bm, MFF_IP_PROTO);
         /* Fall through. */
@@ -540,6 +548,9 @@ mf_is_value_valid(const struct mf_field *mf, const union 
mf_value *value)
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_TYPE:
     case MFF_ICMPV6_CODE:
+    case MFF_IGMP_TYPE:
+    case MFF_IGMP_CODE:
+    case MFF_IGMP_GROUP:
     case MFF_ND_TARGET:
     case MFF_ND_SLL:
     case MFF_ND_TLL:
@@ -818,14 +829,20 @@ mf_get_value(const struct mf_field *mf, const struct flow 
*flow,
 
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV6_TYPE:
+    case MFF_IGMP_TYPE:
         value->u8 = ntohs(flow->tp_src);
         break;
 
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
+    case MFF_IGMP_CODE:
         value->u8 = ntohs(flow->tp_dst);
         break;
 
+    case MFF_IGMP_GROUP:
+        value->be32 = flow->igmp_group_ip4;
+        break;
+
     case MFF_ND_TARGET:
         value->ipv6 = flow->nd_target;
         break;
@@ -1072,14 +1089,20 @@ mf_set_value(const struct mf_field *mf,
 
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV6_TYPE:
+    case MFF_IGMP_TYPE:
         match_set_icmp_type(match, value->u8);
         break;
 
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
+    case MFF_IGMP_CODE:
         match_set_icmp_code(match, value->u8);
         break;
 
+    case MFF_IGMP_GROUP:
+        match_set_igmp_group(match, value->be32);
+        break;
+
     case MFF_ND_TARGET:
         match_set_nd_target(match, &value->ipv6);
         break;
@@ -1381,14 +1404,20 @@ mf_set_flow_value(const struct mf_field *mf,
 
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV6_TYPE:
+    case MFF_IGMP_TYPE:
         flow->tp_src = htons(value->u8);
         break;
 
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
+    case MFF_IGMP_CODE:
         flow->tp_dst = htons(value->u8);
         break;
 
+    case MFF_IGMP_GROUP:
+        flow->igmp_group_ip4 = value->be32;
+        break;
+
     case MFF_ND_TARGET:
         flow->nd_target = value->ipv6;
         break;
@@ -1689,6 +1718,7 @@ mf_set_wild(const struct mf_field *mf, struct match 
*match, char **err_str)
     case MFF_SCTP_SRC:
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV6_TYPE:
+    case MFF_IGMP_TYPE:
         match->wc.masks.tp_src = htons(0);
         match->flow.tp_src = htons(0);
         break;
@@ -1698,10 +1728,15 @@ mf_set_wild(const struct mf_field *mf, struct match 
*match, char **err_str)
     case MFF_SCTP_DST:
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
+    case MFF_IGMP_CODE:
         match->wc.masks.tp_dst = htons(0);
         match->flow.tp_dst = htons(0);
         break;
 
+    case MFF_IGMP_GROUP:
+        match_set_igmp_group_masked(match, htonl(0), htonl(0));
+        break;
+
     case MFF_TCP_FLAGS:
         match->wc.masks.tcp_flags = htons(0);
         match->flow.tcp_flags = htons(0);
@@ -1782,6 +1817,10 @@ mf_set(const struct mf_field *mf,
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_TYPE:
     case MFF_ICMPV6_CODE:
+    case MFF_IGMP_TYPE:
+    case MFF_IGMP_CODE:
+        /* All of these are non-maskable, so no protocol can support masked
+         * match on them. */
         return OFPUTIL_P_NONE;
 
     case MFF_DP_HASH:
@@ -1887,6 +1926,10 @@ mf_set(const struct mf_field *mf,
         match_set_nw_dst_masked(match, value->be32, mask->be32);
         break;
 
+    case MFF_IGMP_GROUP:
+        match_set_igmp_group_masked(match, value->be32, mask->be32);
+        break;
+
     case MFF_IPV6_SRC:
         match_set_ipv6_src_masked(match, &value->ipv6, &mask->ipv6);
         break;
diff --git a/lib/meta-flow.h b/lib/meta-flow.h
index 71c238d..40956db 100644
--- a/lib/meta-flow.h
+++ b/lib/meta-flow.h
@@ -1704,6 +1704,52 @@ enum OVS_PACKED_ENUM mf_field_id {
      */
     MFF_ND_TLL,
 
+/* ## ---- ## */
+/* ## IGMP ## */
+/* ## ---- ## */
+
+    /* "igmp_type".
+     *
+     * IGMP type.
+     *
+     * Type: u8.
+     * Maskable: no.
+     * Formatting: decimal.
+     * Prerequisites: IGMP.
+     * Access: read-only.
+     * NXM: NXM_NX_IGMP_TYPE(111) since v2.5.
+     * OXM: none.
+     */
+    MFF_IGMP_TYPE,
+
+    /* "igmp_code".
+     *
+     * IGMP code.
+     *
+     * Type: u8.
+     * Maskable: no.
+     * Formatting: decimal.
+     * Prerequisites: IGMP.
+     * Access: read-only.
+     * NXM: NXM_NX_IGMP_CODE(112) since v2.5.
+     * OXM: none.
+     */
+    MFF_IGMP_CODE,
+
+    /* "igmp_group".
+     *
+     * IGMP group.
+     *
+     * Type: be32.
+     * Maskable: bitwise.
+     * Formatting: IPv4.
+     * Prerequisites: IGMP.
+     * Access: read-only.
+     * NXM: NXM_NX_IGMP_GROUP(113) since v2.5.
+     * OXM: none.
+     */
+    MFF_IGMP_GROUP,
+
     MFF_N_IDS
 };
 
@@ -1792,6 +1838,7 @@ enum OVS_PACKED_ENUM mf_prereqs {
     MFP_SCTP,                   /* On IPv4 or IPv6. */
     MFP_ICMPV4,
     MFP_ICMPV6,
+    MFP_IGMP,                   /* An IPv4 protocol only. */
 
     /* L2+L3+L4 requirements. */
     MFP_ND,
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 11bcd95..5198b07 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -883,6 +883,15 @@ nxm_put_ip(struct ofpbuf *b, const struct match *match, 
enum ofp_version oxm)
                                        flow->arp_tha, match->wc.masks.arp_tha);
                 }
             }
+        } else if (is_igmp(flow)) {
+            if (match->wc.masks.tp_src) {
+                nxm_put_8(b, MFF_IGMP_TYPE, oxm, ntohs(flow->tp_src));
+            }
+            if (match->wc.masks.tp_dst) {
+                nxm_put_8(b, MFF_IGMP_CODE, oxm, ntohs(flow->tp_dst));
+            }
+            nxm_put_32m(b, MFF_IGMP_GROUP, oxm, flow->igmp_group_ip4,
+                        match->wc.masks.igmp_group_ip4);
         }
     }
 }
diff --git a/tests/ofproto.at b/tests/ofproto.at
index c22d79f..d0425a9 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -1858,6 +1858,9 @@ 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
+      igmp_type: exact match or wildcard
+      igmp_code: exact match or wildcard
+      igmp_group: arbitrary mask
 
 ' $1
 }
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index 2923cf2..b4d1d0f 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -689,6 +689,25 @@ NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(00) 
NXM_OF_ICMP_CODE(10)
 NXM_OF_ETH_TYPE(0800) NXM_OF_ICMP_CODE(10)
 NXM_OF_ICMP_CODE(00)
 
+# IGMP type
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(02) NXM_NX_IGMP_TYPE(11)
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(00) NXM_NX_IGMP_TYPE(10)
+
+# IGMP code
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(02) NXM_NX_IGMP_CODE(7f)
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(00) NXM_NX_IGMP_CODE(10)
+NXM_OF_ETH_TYPE(0800) NXM_NX_IGMP_CODE(10)
+NXM_NX_IGMP_CODE(00)
+
+# IGMP Group
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(02) NXM_NX_IGMP_GROUP(e0000001)
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(02) 
NXM_NX_IGMP_GROUP_W(e0000000/FFFF0000)
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(02) 
NXM_NX_IGMP_GROUP_W(e0000001/5a5a5a5a)
+NXM_OF_ETH_TYPE(0800) NXM_OF_IP_PROTO(02) 
NXM_NX_IGMP_GROUP_W(e0000001/ffffffff)
+NXM_OF_ETH_TYPE(0800) NXM_NX_IGMP_GROUP(e0000001)
+NXM_NX_IGMP_GROUP(e0000001)
+NXM_OF_ETH_TYPE(0806) NXM_OF_IP_PROTO(02) NXM_NX_IGMP_GROUP(e0000001)
+
 # ARP opcode
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_OP(0001)
 NXM_OF_ETH_TYPE(0806) NXM_OF_ARP_OP(1111)
@@ -991,6 +1010,25 @@ nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
+# IGMP type
+NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(02), NXM_NX_IGMP_TYPE(11)
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+
+# IGMP code
+NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(02), NXM_NX_IGMP_CODE(7f)
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+
+# IGMP Group
+NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(02), NXM_NX_IGMP_GROUP(e0000001)
+NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(02), 
NXM_NX_IGMP_GROUP_W(e0000000/ffff0000)
+nx_pull_match() returned error OFPBMC_BAD_WILDCARDS
+NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(02), NXM_NX_IGMP_GROUP(e0000001)
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+
 # ARP opcode
 NXM_OF_ETH_TYPE(0806), NXM_OF_ARP_OP(0001)
 nx_pull_match() returned error OFPBMC_BAD_VALUE
-- 
2.1.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to