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