From 8087f5ff825cae3a699e5a60ca6dd0deb10fc8e5 Mon Sep 17 00:00:00 2001 From: Mehak Mahajan Date: Fri, 2 Nov 2012 11:43:46 -0700 Subject: [PATCH] Process RARP packets with ethertype 0x8035 similar to ARP packets. With this commit, OVS will match the data in the RARP packets having ethertype 0x8035, in the same way as the data in the ARP packets. Signed-off-by: Mehak Mahajan --- NEWS | 3 +- datapath/flow.c | 9 +++-- debian/changelog | 3 +- include/openflow/nicira-ext.h | 6 +-- lib/flow.c | 6 ++- lib/match.c | 17 ++++++--- lib/meta-flow.c | 3 +- lib/nx-match.c | 3 +- lib/odp-util.c | 6 ++- lib/ofp-parse.c | 3 +- lib/ofp-print.c | 5 ++- lib/ofp-util.c | 8 ++-- tests/ofp-print.at | 2 +- tests/ovs-ofctl.at | 70 +++++++++++++++++++++++++++++++++++ utilities/ovs-ofctl.8.in | 25 +++++++++---- 15 files changed, 137 insertions(+), 32 deletions(-) diff --git a/NEWS b/NEWS index c936b61e3..dd2ab1e60 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ post-v1.9.0 -------------------- - + - The data in the RARP packets can now be matched in the same way as the + data in ARP packets. v1.9.0 - xx xxx xxxx -------------------- diff --git a/datapath/flow.c b/datapath/flow.c index c70daeed7..44e71e627 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -725,7 +725,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, } } - } else if (key->eth.type == htons(ETH_P_ARP) && arphdr_ok(skb)) { + } else if ((key->eth.type == htons(ETH_P_ARP) || + key->eth.type == htons(ETH_P_RARP)) && arphdr_ok(skb)) { struct arp_eth_header *arp; arp = (struct arp_eth_header *)skb_network_header(skb); @@ -1173,7 +1174,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, if (err) return err; } - } else if (swkey->eth.type == htons(ETH_P_ARP)) { + } else if (swkey->eth.type == htons(ETH_P_ARP) || + swkey->eth.type == htons(ETH_P_RARP)) { const struct ovs_key_arp *arp_key; if (!(attrs & (1 << OVS_KEY_ATTR_ARP))) @@ -1361,7 +1363,8 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) ipv6_key->ipv6_tclass = swkey->ip.tos; ipv6_key->ipv6_hlimit = swkey->ip.ttl; ipv6_key->ipv6_frag = swkey->ip.frag; - } else if (swkey->eth.type == htons(ETH_P_ARP)) { + } else if (swkey->eth.type == htons(ETH_P_ARP) || + swkey->eth.type == htons(ETH_P_RARP)) { struct ovs_key_arp *arp_key; nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key)); diff --git a/debian/changelog b/debian/changelog index 39673c649..c366623ba 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,8 @@ openvswitch (1.9.90-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - - Nothing yet! Try NEWS... + - The data in the RARP packets can now be matched in the same way as the + data in ARP packets. -- Open vSwitch team Wed, 24 Oct 2012 16:12:57 -0700 diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h index e9790fd57..08ed9fc36 100644 --- a/include/openflow/nicira-ext.h +++ b/include/openflow/nicira-ext.h @@ -1516,7 +1516,7 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24); * otherwise. Only ARP opcodes between 1 and 255 should be specified for * matching. * - * Prereqs: NXM_OF_ETH_TYPE must match 0x0806 exactly. + * Prereqs: NXM_OF_ETH_TYPE must match either 0x0806 or 0x8035. * * Format: 16-bit integer in network byte order. * @@ -1526,7 +1526,7 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24); /* For an Ethernet+IP ARP packet, the source or target protocol address * in the ARP header. Always 0 otherwise. * - * Prereqs: NXM_OF_ETH_TYPE must match 0x0806 exactly. + * Prereqs: NXM_OF_ETH_TYPE must match either 0x0806 or 0x8035. * * Format: 32-bit integer in network byte order. * @@ -1593,7 +1593,7 @@ OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24); /* For an Ethernet+IP ARP packet, the source or target hardware address * in the ARP header. Always 0 otherwise. * - * Prereqs: NXM_OF_ETH_TYPE must match 0x0806 exactly. + * Prereqs: NXM_OF_ETH_TYPE must match either 0x0806 or 0x8035. * * Format: 48-bit Ethernet MAC address. * diff --git a/lib/flow.c b/lib/flow.c index 75087c943..7084079ea 100644 --- a/lib/flow.c +++ b/lib/flow.c @@ -424,7 +424,8 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority, packet->l7 = b.data; } } - } else if (flow->dl_type == htons(ETH_TYPE_ARP)) { + } else if (flow->dl_type == htons(ETH_TYPE_ARP) || + flow->dl_type == htons(ETH_TYPE_RARP)) { const struct arp_eth_header *arp = pull_arp(&b); if (arp && arp->ar_hrd == htons(1) && arp->ar_pro == htons(ETH_TYPE_IP) @@ -808,7 +809,8 @@ flow_compose(struct ofpbuf *b, const struct flow *flow) ip->ip_csum = csum(ip, sizeof *ip); } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { /* XXX */ - } else if (flow->dl_type == htons(ETH_TYPE_ARP)) { + } else if (flow->dl_type == htons(ETH_TYPE_ARP) || + flow->dl_type == htons(ETH_TYPE_RARP)) { struct arp_eth_header *arp; b->l3 = arp = ofpbuf_put_zeros(b, sizeof *arp); diff --git a/lib/match.c b/lib/match.c index 6a4fec72f..81b717348 100644 --- a/lib/match.c +++ b/lib/match.c @@ -81,12 +81,14 @@ match_wc_init(struct match *match, const struct flow *flow) memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst); memset(&wc->masks.ipv6_label, 0xff, sizeof wc->masks.ipv6_label); } else if (flow->dl_type == htons(ETH_TYPE_IP) || - (flow->dl_type == htons(ETH_TYPE_ARP))) { + (flow->dl_type == htons(ETH_TYPE_ARP)) || + (flow->dl_type == htons(ETH_TYPE_RARP))) { memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src); memset(&wc->masks.nw_dst, 0xff, sizeof wc->masks.nw_dst); } - if (flow->dl_type == htons(ETH_TYPE_ARP)) { + if (flow->dl_type == htons(ETH_TYPE_ARP) || + flow->dl_type == htons(ETH_TYPE_RARP)) { memset(&wc->masks.arp_sha, 0xff, sizeof wc->masks.arp_sha); memset(&wc->masks.arp_tha, 0xff, sizeof wc->masks.arp_tha); } @@ -695,6 +697,8 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) } } else if (f->dl_type == htons(ETH_TYPE_ARP)) { ds_put_cstr(s, "arp,"); + } else if (f->dl_type == htons(ETH_TYPE_RARP)) { + ds_put_cstr(s, "rarp,"); } else { skip_type = false; } @@ -780,7 +784,8 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) ntohl(wc->masks.ipv6_label)); } } - } else if (f->dl_type == htons(ETH_TYPE_ARP)) { + } else if (f->dl_type == htons(ETH_TYPE_ARP) || + f->dl_type == htons(ETH_TYPE_RARP)) { format_ip_netmask(s, "arp_spa", f->nw_src, wc->masks.nw_src); format_ip_netmask(s, "arp_tpa", f->nw_dst, wc->masks.nw_dst); } else { @@ -788,13 +793,15 @@ match_format(const struct match *match, struct ds *s, unsigned int priority) format_ip_netmask(s, "nw_dst", f->nw_dst, wc->masks.nw_dst); } if (!skip_proto && wc->masks.nw_proto) { - if (f->dl_type == htons(ETH_TYPE_ARP)) { + if (f->dl_type == htons(ETH_TYPE_ARP) || + f->dl_type == htons(ETH_TYPE_RARP)) { ds_put_format(s, "arp_op=%"PRIu8",", f->nw_proto); } else { ds_put_format(s, "nw_proto=%"PRIu8",", f->nw_proto); } } - if (f->dl_type == htons(ETH_TYPE_ARP)) { + if (f->dl_type == htons(ETH_TYPE_ARP) || + f->dl_type == htons(ETH_TYPE_RARP)) { format_eth_masked(s, "arp_sha", f->arp_sha, wc->masks.arp_sha); format_eth_masked(s, "arp_tha", f->arp_tha, wc->masks.arp_tha); } diff --git a/lib/meta-flow.c b/lib/meta-flow.c index 4fa05ae74..0b97049a4 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -834,7 +834,8 @@ mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow) return true; case MFP_ARP: - return flow->dl_type == htons(ETH_TYPE_ARP); + return (flow->dl_type == htons(ETH_TYPE_ARP) || + flow->dl_type == htons(ETH_TYPE_RARP)); case MFP_IPV4: return flow->dl_type == htons(ETH_TYPE_IP); case MFP_IPV6: diff --git a/lib/nx-match.c b/lib/nx-match.c index 991899403..9c4088f1a 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -626,7 +626,8 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match, flow->arp_tha, match->wc.masks.arp_tha); } } - } else if (flow->dl_type == htons(ETH_TYPE_ARP)) { + } else if (flow->dl_type == htons(ETH_TYPE_ARP) || + flow->dl_type == htons(ETH_TYPE_RARP)) { /* ARP. */ if (match->wc.masks.nw_proto) { nxm_put_16(b, oxm ? OXM_OF_ARP_OP : NXM_OF_ARP_OP, diff --git a/lib/odp-util.c b/lib/odp-util.c index caf5188e5..08823e276 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -1355,7 +1355,8 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow, ipv6_key->ipv6_tclass = flow->nw_tos; ipv6_key->ipv6_hlimit = flow->nw_ttl; ipv6_key->ipv6_frag = ovs_to_odp_frag(flow->nw_frag); - } else if (flow->dl_type == htons(ETH_TYPE_ARP)) { + } else if (flow->dl_type == htons(ETH_TYPE_ARP) || + flow->dl_type == htons(ETH_TYPE_RARP)) { struct ovs_key_arp *arp_key; arp_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ARP, @@ -1611,7 +1612,8 @@ parse_l3_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], return ODP_FIT_ERROR; } } - } else if (flow->dl_type == htons(ETH_TYPE_ARP)) { + } else if (flow->dl_type == htons(ETH_TYPE_ARP) || + flow->dl_type == htons(ETH_TYPE_RARP)) { expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ARP; if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ARP)) { const struct ovs_key_arp *arp_key; diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index dedfb7e27..054db60e4 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -720,7 +720,8 @@ parse_protocol(const char *name, const struct protocol **p_out) { "icmp6", ETH_TYPE_IPV6, IPPROTO_ICMPV6 }, { "tcp6", ETH_TYPE_IPV6, IPPROTO_TCP }, { "udp6", ETH_TYPE_IPV6, IPPROTO_UDP }, - }; + { "rarp", ETH_TYPE_RARP, 0}, +}; const struct protocol *p; for (p = protocols; p < &protocols[ARRAY_SIZE(protocols)]; p++) { diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 8654783a2..cafc665d7 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -617,6 +617,8 @@ ofp10_match_to_string(const struct ofp10_match *om, int verbosity) } } else if (om->dl_type == htons(ETH_TYPE_ARP)) { ds_put_cstr(&f, "arp,"); + } else if (om->dl_type == htons(ETH_TYPE_RARP)){ + ds_put_cstr(&f, "rarp,"); } else { skip_type = false; } @@ -642,7 +644,8 @@ ofp10_match_to_string(const struct ofp10_match *om, int verbosity) (w & OFPFW10_NW_DST_MASK) >> OFPFW10_NW_DST_SHIFT, verbosity); if (!skip_proto) { - if (om->dl_type == htons(ETH_TYPE_ARP)) { + if (om->dl_type == htons(ETH_TYPE_ARP) || + om->dl_type == htons(ETH_TYPE_RARP)) { print_wild(&f, "arp_op=", w & OFPFW10_NW_PROTO, verbosity, "%u", om->nw_proto); } else { diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 34255da2f..b81476869 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -305,7 +305,7 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch, uint16_t wc = ntohl(ofmatch->wildcards); uint8_t dl_src_mask[ETH_ADDR_LEN]; uint8_t dl_dst_mask[ETH_ADDR_LEN]; - bool ipv4, arp; + bool ipv4, arp, rarp; int i; match_init_catchall(match); @@ -370,6 +370,7 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch, ipv4 = match->flow.dl_type == htons(ETH_TYPE_IP); arp = match->flow.dl_type == htons(ETH_TYPE_ARP); + rarp = match->flow.dl_type == htons(ETH_TYPE_RARP); if (ipv4 && !(wc & OFPFW11_NW_TOS)) { if (ofmatch->nw_tos & ~IP_DSCP_MASK) { @@ -380,7 +381,7 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch, match_set_nw_dscp(match, ofmatch->nw_tos); } - if (ipv4 || arp) { + if (ipv4 || arp || rarp) { if (!(wc & OFPFW11_NW_PROTO)) { match_set_nw_proto(match, ofmatch->nw_proto); } @@ -3789,7 +3790,8 @@ ofputil_normalize_match__(struct match *match, bool may_log) may_match |= MAY_ND_TARGET | MAY_ARP_THA; } } - } else if (match->flow.dl_type == htons(ETH_TYPE_ARP)) { + } else if (match->flow.dl_type == htons(ETH_TYPE_ARP) || + match->flow.dl_type == htons(ETH_TYPE_RARP)) { may_match = MAY_NW_PROTO | MAY_NW_ADDR | MAY_ARP_SHA | MAY_ARP_THA; } else { may_match = 0; diff --git a/tests/ofp-print.at b/tests/ofp-print.at index 6133fff6d..963f13c9a 100644 --- a/tests/ofp-print.at +++ b/tests/ofp-print.at @@ -351,7 +351,7 @@ AT_CHECK([ovs-ofctl ofp-print "\ 00 00 00 23 20 83 c1 5f 00 00 00 00 \ "], [0], [dnl OFPT_PACKET_IN (OF1.2) (xid=0x0): total_len=42 in_port=LOCAL (via no_match) data_len=42 buffer=0xffffff00 -priority=0,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=00:23:20:83:c1:5f,dl_dst=ff:ff:ff:ff:ff:ff,dl_type=0x8035 +priority=0,rarp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=00:23:20:83:c1:5f,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_op=3,arp_sha=00:23:20:83:c1:5f,arp_tha=00:23:20:83:c1:5f ]) AT_CLEANUP diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index 1fa1a342f..958982f0a 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -377,6 +377,41 @@ NXM_OF_ETH_TYPE(0806) NXM_NX_ARP_THA(0002e30f80a4) NXM_OF_ETH_TYPE(0800) NXM_NX_ARP_THA(0002e30f80a4) NXM_NX_ARP_THA(0002e30f80a4) +# RARP opcode +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_OP(0003) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_OP(1111) +NXM_OF_ETH_TYPE(0000) NXM_OF_ARP_OP(0003) +NXM_OF_ARP_OP(0003) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_OP(0003) NXM_OF_ARP_OP(0003) + +# RARP source protocol address +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_SPA(ac100014) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_SPA_W(C0a81234/FFFFFF00) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_SPA_W(C0a81234/aaaaaa00) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_SPA_W(C0a81234/ffffffff) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_SPA_W(C0a81234/00000000) +NXM_OF_ETH_TYPE(0800) NXM_OF_ARP_SPA(ac100014) +NXM_OF_ARP_SPA_W(C0D8fedc/FFFF0000) + +# RARP destination protocol address +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_TPA(ac100014) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_TPA_W(C0a812fe/FFFFFF00) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_TPA_W(C0a81234/77777777) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_TPA_W(C0a81234/ffffffff) +NXM_OF_ETH_TYPE(8035) NXM_OF_ARP_TPA_W(C0a81234/00000000) +NXM_OF_ETH_TYPE(0800) NXM_OF_ARP_TPA(ac100014) +NXM_OF_ARP_TPA_W(C0D80000/FFFF0000) + +# RARP source hardware address +NXM_OF_ETH_TYPE(8035) NXM_NX_ARP_SHA(0002e30f80a4) +NXM_OF_ETH_TYPE(0800) NXM_NX_ARP_SHA(0002e30f80a4) +NXM_NX_ARP_SHA(0002e30f80a4) + +# RARP destination hardware address +NXM_OF_ETH_TYPE(8035) NXM_NX_ARP_THA(0002e30f80a4) +NXM_OF_ETH_TYPE(0800) NXM_NX_ARP_THA(0002e30f80a4) +NXM_NX_ARP_THA(0002e30f80a4) + # IPv6 source NXM_OF_ETH_TYPE(86dd) NXM_NX_IPV6_SRC(20010db83c4d00010002000300040005) NXM_OF_ETH_TYPE(0800) NXM_NX_IPV6_SRC(20010db83c4d00010002000300040005) @@ -629,6 +664,41 @@ NXM_OF_ETH_TYPE(0806), NXM_NX_ARP_THA(0002e30f80a4) nx_pull_match() returned error OFPBMC_BAD_PREREQ nx_pull_match() returned error OFPBMC_BAD_PREREQ +# RARP opcode +NXM_OF_ETH_TYPE(8035), NXM_OF_ARP_OP(0003) +nx_pull_match() returned error OFPBMC_BAD_VALUE +nx_pull_match() returned error OFPBMC_BAD_PREREQ +nx_pull_match() returned error OFPBMC_BAD_PREREQ +nx_pull_match() returned error OFPBMC_DUP_FIELD + +# RARP source protocol address +NXM_OF_ETH_TYPE(8035), NXM_OF_ARP_SPA(ac100014) +NXM_OF_ETH_TYPE(8035), NXM_OF_ARP_SPA_W(c0a81200/ffffff00) +NXM_OF_ETH_TYPE(8035), NXM_OF_ARP_SPA_W(80a80200/aaaaaa00) +NXM_OF_ETH_TYPE(8035), NXM_OF_ARP_SPA(c0a81234) +NXM_OF_ETH_TYPE(8035) +nx_pull_match() returned error OFPBMC_BAD_PREREQ +nx_pull_match() returned error OFPBMC_BAD_PREREQ + +# RARP destination protocol address +NXM_OF_ETH_TYPE(8035), NXM_OF_ARP_TPA(ac100014) +NXM_OF_ETH_TYPE(8035), NXM_OF_ARP_TPA_W(c0a81200/ffffff00) +NXM_OF_ETH_TYPE(8035), NXM_OF_ARP_TPA_W(40201234/77777777) +NXM_OF_ETH_TYPE(8035), NXM_OF_ARP_TPA(c0a81234) +NXM_OF_ETH_TYPE(8035) +nx_pull_match() returned error OFPBMC_BAD_PREREQ +nx_pull_match() returned error OFPBMC_BAD_PREREQ + +# RARP source hardware address +NXM_OF_ETH_TYPE(8035), NXM_NX_ARP_SHA(0002e30f80a4) +nx_pull_match() returned error OFPBMC_BAD_PREREQ +nx_pull_match() returned error OFPBMC_BAD_PREREQ + +# RARP destination hardware address +NXM_OF_ETH_TYPE(8035), NXM_NX_ARP_THA(0002e30f80a4) +nx_pull_match() returned error OFPBMC_BAD_PREREQ +nx_pull_match() returned error OFPBMC_BAD_PREREQ + # IPv6 source NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC(20010db83c4d00010002000300040005) nx_pull_match() returned error OFPBMC_BAD_PREREQ diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 9ea09737b..7b6939f25 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -468,8 +468,12 @@ When \fBdl_type=0x0806\fR or \fBarp\fR is specified, matches the \fBar_spa\fR or \fBar_tpa\fR field, respectively, in ARP packets for IPv4 and Ethernet. .IP -When \fBdl_type\fR is wildcarded or set to a value other than 0x0800 -or 0x0806, the values of \fBnw_src\fR and \fBnw_dst\fR are ignored +When \fBdl_type=0x8035\fR or \fBrarp\fR is specified, matches the +\fBar_spa\fR or \fBar_tpa\fR field, respectively, in RARP packets for +IPv4 and Ethernet. +.IP +When \fBdl_type\fR is wildcarded or set to a value other than 0x0800, +0x0806, or 0x8035, the values of \fBnw_src\fR and \fBnw_dst\fR are ignored (see \fBFlow Syntax\fR above). . .IP \fBnw_proto=\fIproto\fR @@ -488,9 +492,13 @@ When \fBarp\fR or \fBdl_type=0x0806\fR is specified, matches the lower 8 bits of the ARP opcode. ARP opcodes greater than 255 are treated as 0. .IP +When \fBrarp\fR or \fBdl_type=0x8035\fR is specified, matches the lower +8 bits of the ARP opcode. ARP opcodes greater than 255 are treated as +0. +.IP When \fBdl_type\fR is wildcarded or set to a value other than 0x0800, -0x0806, or 0x86dd, the value of \fBnw_proto\fR is ignored (see \fBFlow -Syntax\fR above). +0x0806, 0x8035 or 0x86dd, the value of \fBnw_proto\fR is ignored (see +\fBFlow Syntax\fR above). . .IP \fBnw_tos=\fItos\fR Matches IP ToS/DSCP or IPv6 traffic class field \fItos\fR, which is @@ -645,6 +653,9 @@ Same as \fBdl_type=0x0800,nw_proto=17\fR. .IP \fBarp\fR Same as \fBdl_type=0x0806\fR. . +.IP \fBrarp\fR +Same as \fBdl_type=0x8035\fR. +. .PP The following field assignments require support for the NXM (Nicira Extended Match) extension to OpenFlow. When one of these is specified, @@ -712,9 +723,9 @@ command, above, for more details. . .IP \fBarp_sha=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR .IQ \fBarp_tha=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR -When \fBdl_type\fR specifies ARP, \fBarp_sha\fR and \fBarp_tha\fR match -the source and target hardware address, respectively. An address is -specified as 6 pairs of hexadecimal digits delimited by colons. +When \fBdl_type\fR specifies either ARP or RARP, \fBarp_sha\fR and +\fBarp_tha\fR match the source and target hardware address, respectively. An +address is specified as 6 pairs of hexadecimal digits delimited by colons. . .IP \fBipv6_src=\fIipv6\fR[\fB/\fInetmask\fR] .IQ \fBipv6_dst=\fIipv6\fR[\fB/\fInetmask\fR] -- 2.43.0