/* Hash table of 'nxm_fields'. */
static struct hmap all_nxm_fields = HMAP_INITIALIZER(&all_nxm_fields);
-/* Possible masks for NXM_OF_ETH_DST_W. */
-static const uint8_t eth_all_0s[ETH_ADDR_LEN]
- = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const uint8_t eth_all_1s[ETH_ADDR_LEN]
- = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-static const uint8_t eth_mcast_1[ETH_ADDR_LEN]
- = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00};
-static const uint8_t eth_mcast_0[ETH_ADDR_LEN]
- = {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff};
-
static void
nxm_init(void)
{
if ((wc->wildcards & (FWW_DL_DST | FWW_ETH_MCAST))
!= (FWW_DL_DST | FWW_ETH_MCAST)) {
return NXM_DUP_TYPE;
- } else if (eth_addr_equals(mask, eth_mcast_1)) {
- wc->wildcards &= ~FWW_ETH_MCAST;
- flow->dl_dst[0] = *(uint8_t *) value & 0x01;
- return 0;
- } else if (eth_addr_equals(mask, eth_mcast_0)) {
- wc->wildcards &= ~FWW_DL_DST;
- memcpy(flow->dl_dst, value, ETH_ADDR_LEN);
- flow->dl_dst[0] &= 0xfe;
- return 0;
- } else if (eth_addr_equals(mask, eth_all_0s)) {
- return 0;
- } else if (eth_addr_equals(mask, eth_all_1s)) {
- wc->wildcards &= ~(FWW_DL_DST | FWW_ETH_MCAST);
- memcpy(flow->dl_dst, value, ETH_ADDR_LEN);
+ } else if (flow_wildcards_is_dl_dst_mask_valid(mask)) {
+ cls_rule_set_dl_dst_masked(rule, value, mask);
return 0;
} else {
return NXM_BAD_MASK;
static void
nxm_put_eth_dst(struct ofpbuf *b,
- uint32_t wc, const uint8_t value[ETH_ADDR_LEN])
+ flow_wildcards_t wc, const uint8_t value[ETH_ADDR_LEN])
{
switch (wc & (FWW_DL_DST | FWW_ETH_MCAST)) {
case FWW_DL_DST | FWW_ETH_MCAST:
break;
- case FWW_DL_DST:
- nxm_put_header(b, NXM_OF_ETH_DST_W);
- ofpbuf_put(b, value, ETH_ADDR_LEN);
- ofpbuf_put(b, eth_mcast_1, ETH_ADDR_LEN);
- break;
- case FWW_ETH_MCAST:
+ default:
nxm_put_header(b, NXM_OF_ETH_DST_W);
ofpbuf_put(b, value, ETH_ADDR_LEN);
- ofpbuf_put(b, eth_mcast_0, ETH_ADDR_LEN);
+ ofpbuf_put(b, flow_wildcards_to_dl_dst_mask(wc), ETH_ADDR_LEN);
break;
case 0:
nxm_put_eth(b, NXM_OF_ETH_DST, value);
case IPPROTO_ICMPV6:
if (!(wc & FWW_TP_SRC)) {
nxm_put_8(b, NXM_NX_ICMPV6_TYPE, ntohs(flow->tp_src));
+
+ if (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) ||
+ flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
+ if (!(wc & FWW_ND_TARGET)) {
+ nxm_put_ipv6(b, NXM_NX_ND_TARGET, &flow->nd_target,
+ &in6addr_exact);
+ }
+ if (!(wc & FWW_ARP_SHA)
+ && flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)) {
+ nxm_put_eth(b, NXM_NX_ND_SLL, flow->arp_sha);
+ }
+ if (!(wc & FWW_ARP_THA)
+ && flow->tp_src == htons(ND_NEIGHBOR_ADVERT)) {
+ nxm_put_eth(b, NXM_NX_ND_TLL, flow->arp_tha);
+ }
+ }
}
if (!(wc & FWW_TP_DST)) {
nxm_put_8(b, NXM_NX_ICMPV6_CODE, ntohs(flow->tp_dst));
}
- if (!(wc & FWW_ND_TARGET)) {
- nxm_put_ipv6(b, NXM_NX_ND_TARGET, &flow->nd_target,
- &in6addr_exact);
- }
- if (!(wc & FWW_ARP_SHA)) {
- nxm_put_eth(b, NXM_NX_ND_SLL, flow->arp_sha);
- }
- if (!(wc & FWW_ARP_THA)) {
- nxm_put_eth(b, NXM_NX_ND_TLL, flow->arp_tha);
- }
break;
}
}