+ } else if (!(wc & FWW_DL_TYPE) && flow->dl_type == htons(ETH_TYPE_IPV6)) {
+ /* IPv6. */
+
+ if (!(wc & FWW_NW_TOS)) {
+ nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & 0xfc);
+ }
+ nxm_put_ipv6(b, NXM_NX_IPV6_SRC, &flow->ipv6_src,
+ &cr->wc.ipv6_src_mask);
+ nxm_put_ipv6(b, NXM_NX_IPV6_DST, &flow->ipv6_dst,
+ &cr->wc.ipv6_dst_mask);
+
+ if (!(wc & FWW_NW_PROTO)) {
+ nxm_put_8(b, NXM_OF_IP_PROTO, flow->nw_proto);
+ switch (flow->nw_proto) {
+ /* TCP. */
+ case IPPROTO_TCP:
+ if (!(wc & FWW_TP_SRC)) {
+ nxm_put_16(b, NXM_OF_TCP_SRC, flow->tp_src);
+ }
+ if (!(wc & FWW_TP_DST)) {
+ nxm_put_16(b, NXM_OF_TCP_DST, flow->tp_dst);
+ }
+ break;
+
+ /* UDP. */
+ case IPPROTO_UDP:
+ if (!(wc & FWW_TP_SRC)) {
+ nxm_put_16(b, NXM_OF_UDP_SRC, flow->tp_src);
+ }
+ if (!(wc & FWW_TP_DST)) {
+ nxm_put_16(b, NXM_OF_UDP_DST, flow->tp_dst);
+ }
+ break;
+
+ /* ICMPv6. */
+ 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));
+ }
+ break;
+ }
+ }