This simplifies a few pieces of code and will acquire another user in an
upcoming commit.
Signed-off-by: Ben Pfaff <blp@ovn.org>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <netinet/in.h>
+#include <netinet/icmp6.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
+static inline bool is_nd(const struct flow *flow,
+ struct flow_wildcards *wc)
+{
+ if (is_icmpv6(flow, wc)) {
+ if (wc) {
+ memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst);
+ }
+ if (flow->tp_dst != htons(0)) {
+ return false;
+ }
+
+ if (wc) {
+ memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src);
+ }
+ return (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
+ flow->tp_src == htons(ND_NEIGHBOR_ADVERT));
+ }
+ return false;
+}
+
static inline bool is_igmp(const struct flow *flow, struct flow_wildcards *wc)
{
if (flow->dl_type == htons(ETH_TYPE_IP)) {
static inline bool is_igmp(const struct flow *flow, struct flow_wildcards *wc)
{
if (flow->dl_type == htons(ETH_TYPE_IP)) {
return is_icmpv6(flow, NULL);
case MFP_ND:
return is_icmpv6(flow, NULL);
case MFP_ND:
- return (is_icmpv6(flow, NULL)
- && flow->tp_dst == htons(0)
- && (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
- flow->tp_src == htons(ND_NEIGHBOR_ADVERT)));
+ return is_nd(flow, NULL);
- return (is_icmpv6(flow, NULL)
- && flow->tp_dst == htons(0)
- && (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)));
+ return is_nd(flow, NULL) && flow->tp_src == htons(ND_NEIGHBOR_SOLICIT);
- return (is_icmpv6(flow, NULL)
- && flow->tp_dst == htons(0)
- && (flow->tp_src == htons(ND_NEIGHBOR_ADVERT)));
+ return is_nd(flow, NULL) && flow->tp_src == htons(ND_NEIGHBOR_ADVERT);
nxm_put_8(b, MFF_ICMPV6_CODE, oxm,
ntohs(flow->tp_dst));
}
nxm_put_8(b, MFF_ICMPV6_CODE, oxm,
ntohs(flow->tp_dst));
}
- if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
- flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
+ if (is_nd(flow, NULL)) {
nxm_put_ipv6(b, MFF_ND_TARGET, oxm,
&flow->nd_target, &match->wc.masks.nd_target);
if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
nxm_put_ipv6(b, MFF_ND_TARGET, oxm,
&flow->nd_target, &match->wc.masks.nd_target);
if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
icmpv6_key->icmpv6_type = ntohs(data->tp_src);
icmpv6_key->icmpv6_code = ntohs(data->tp_dst);
icmpv6_key->icmpv6_type = ntohs(data->tp_src);
icmpv6_key->icmpv6_code = ntohs(data->tp_dst);
- if (flow->tp_dst == htons(0)
- && (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)
- || flow->tp_src == htons(ND_NEIGHBOR_ADVERT))
/* Even though 'tp_src' and 'tp_dst' are 16 bits wide, ICMP
* type and code are 8 bits wide. Therefore, an exact match
* looks like htons(0xff), not htons(0xffff). See
/* Even though 'tp_src' and 'tp_dst' are 16 bits wide, ICMP
* type and code are 8 bits wide. Therefore, an exact match
* looks like htons(0xff), not htons(0xffff). See
flow->tp_src = htons(icmpv6_key->icmpv6_type);
flow->tp_dst = htons(icmpv6_key->icmpv6_code);
expected_bit = OVS_KEY_ATTR_ICMPV6;
flow->tp_src = htons(icmpv6_key->icmpv6_type);
flow->tp_dst = htons(icmpv6_key->icmpv6_code);
expected_bit = OVS_KEY_ATTR_ICMPV6;
- if (src_flow->tp_dst == htons(0) &&
- (src_flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
- src_flow->tp_src == htons(ND_NEIGHBOR_ADVERT))) {
+ if (is_nd(src_flow, NULL)) {
if (!is_mask) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;
}
if (!is_mask) {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;
}
tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
const char name[IFNAMSIZ])
{
tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
const char name[IFNAMSIZ])
{
- if (flow->dl_type != htons(ETH_TYPE_IPV6) ||
- flow->nw_proto != IPPROTO_ICMPV6 ||
- flow->tp_dst != htons(0) ||
- flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) {
+ if (!is_nd(flow, NULL) || flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) {
return EINVAL;
}
/* - RFC4861 says Neighbor Advertisements sent in response to unicast Neighbor
return EINVAL;
}
/* - RFC4861 says Neighbor Advertisements sent in response to unicast Neighbor