+static void
+nxm_put_frag(struct ofpbuf *b, const struct match *match)
+{
+ uint8_t nw_frag = match->flow.nw_frag;
+ uint8_t nw_frag_mask = match->wc.masks.nw_frag;
+
+ switch (nw_frag_mask) {
+ case 0:
+ break;
+
+ case FLOW_NW_FRAG_MASK:
+ nxm_put_8(b, NXM_NX_IP_FRAG, nw_frag);
+ break;
+
+ default:
+ nxm_put_8m(b, NXM_NX_IP_FRAG, nw_frag,
+ nw_frag_mask & FLOW_NW_FRAG_MASK);
+ break;
+ }
+}
+
+static void
+nxm_put_ip(struct ofpbuf *b, const struct match *match,
+ uint8_t icmp_proto, uint32_t icmp_type, uint32_t icmp_code,
+ bool oxm)
+{
+ const struct flow *flow = &match->flow;
+
+ nxm_put_frag(b, match);
+
+ if (match->wc.masks.nw_tos & IP_DSCP_MASK) {
+ if (oxm) {
+ nxm_put_8(b, OXM_OF_IP_DSCP, flow->nw_tos >> 2);
+ } else {
+ nxm_put_8(b, NXM_OF_IP_TOS, flow->nw_tos & IP_DSCP_MASK);
+ }
+ }
+
+ if (match->wc.masks.nw_tos & IP_ECN_MASK) {
+ nxm_put_8(b, oxm ? OXM_OF_IP_ECN : NXM_NX_IP_ECN,
+ flow->nw_tos & IP_ECN_MASK);
+ }
+
+ if (!oxm && match->wc.masks.nw_ttl) {
+ nxm_put_8(b, NXM_NX_IP_TTL, flow->nw_ttl);
+ }
+
+ if (match->wc.masks.nw_proto) {
+ nxm_put_8(b, oxm ? OXM_OF_IP_PROTO : NXM_OF_IP_PROTO, flow->nw_proto);
+
+ if (flow->nw_proto == IPPROTO_TCP) {
+ nxm_put_16m(b, oxm ? OXM_OF_TCP_SRC : NXM_OF_TCP_SRC,
+ flow->tp_src, match->wc.masks.tp_src);
+ nxm_put_16m(b, oxm ? OXM_OF_TCP_DST : NXM_OF_TCP_DST,
+ flow->tp_dst, match->wc.masks.tp_dst);
+ nxm_put_16m(b, NXM_NX_TCP_FLAGS,
+ flow->tcp_flags, match->wc.masks.tcp_flags);
+ } else if (flow->nw_proto == IPPROTO_UDP) {
+ nxm_put_16m(b, oxm ? OXM_OF_UDP_SRC : NXM_OF_UDP_SRC,
+ flow->tp_src, match->wc.masks.tp_src);
+ nxm_put_16m(b, oxm ? OXM_OF_UDP_DST : NXM_OF_UDP_DST,
+ flow->tp_dst, match->wc.masks.tp_dst);
+ } else if (flow->nw_proto == IPPROTO_SCTP) {
+ nxm_put_16m(b, OXM_OF_SCTP_SRC, flow->tp_src,
+ match->wc.masks.tp_src);
+ nxm_put_16m(b, OXM_OF_SCTP_DST, flow->tp_dst,
+ match->wc.masks.tp_dst);
+ } else if (flow->nw_proto == icmp_proto) {
+ if (match->wc.masks.tp_src) {
+ nxm_put_8(b, icmp_type, ntohs(flow->tp_src));
+ }
+ if (match->wc.masks.tp_dst) {
+ nxm_put_8(b, icmp_code, ntohs(flow->tp_dst));
+ }
+ }
+ }
+}
+
+/* Appends to 'b' the nx_match format that expresses 'match'. For Flow Mod and
+ * Flow Stats Requests messages, a 'cookie' and 'cookie_mask' may be supplied.
+ * Otherwise, 'cookie_mask' should be zero.