datapath: add skb mark matching and set action
authorAnsis Atteka <aatteka@nicira.com>
Tue, 13 Nov 2012 17:19:36 +0000 (19:19 +0200)
committerAnsis Atteka <aatteka@nicira.com>
Thu, 22 Nov 2012 00:19:30 +0000 (16:19 -0800)
This patch adds support for skb mark matching and set action.

Acked-by: Jesse Gross <jesse@nicira.com>
Signed-off-by: Ansis Atteka <aatteka@nicira.com>
24 files changed:
NEWS
datapath/actions.c
datapath/compat.h
datapath/datapath.c
datapath/flow.c
datapath/flow.h
debian/changelog
include/linux/openvswitch.h
lib/dpif-linux.c
lib/dpif-netdev.c
lib/flow.c
lib/flow.h
lib/learning-switch.c
lib/match.c
lib/nx-match.c
lib/odp-util.c
lib/odp-util.h
lib/ofp-print.c
lib/ofp-util.c
ofproto/ofproto-dpif.c
ofproto/ofproto-unixctl.man
ofproto/ofproto.c
tests/odp.at
tests/test-flows.c

diff --git a/NEWS b/NEWS
index 037296574b90a8f6e48ca2d929f5a837c2ba94e6..bb80bebfe5984ef742360ad7faaf791180c65c7a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,7 +7,9 @@ v1.9.0 - xx xxx xxxx
     - The tunneling code no longer assumes input and output keys are symmetric.
       If they are not, PMTUD needs to be disabled for tunneling to work. Note
       this only applies to flow-based keys.
-    - Datapath: Support for ipv6 set action.
+    - Datapath:
+      - Support for ipv6 set action.
+      - SKB mark matching and setting.
     - FreeBSD is now a supported platform, thanks to code contributions from
       Gaetano Catalli, Ed Maste, and Giuseppe Lettieri.
     - ovs-bugtool: New --ovs option to report only OVS related information.
index 76c9823a5259268e8e5a62aa0748ef3f279bfc8d..faa6a0023df87d67adab6e09afff9eae7ed54d60 100644 (file)
@@ -435,6 +435,10 @@ static int execute_set_action(struct sk_buff *skb,
                skb->priority = nla_get_u32(nested_attr);
                break;
 
+       case OVS_KEY_ATTR_SKB_MARK:
+               skb_set_mark(skb, nla_get_u32(nested_attr));
+               break;
+
        case OVS_KEY_ATTR_TUN_ID:
                /* If we're only using the TUN_ID action, store the value in a
                 * temporary instance of struct ovs_key_ipv4_tunnel on the stack.
index 3113b961e7b4ba336a07e3bfa189df2f76f84f64..3b8d577ef1284c64724370d8a1f90fb8b9855f5b 100644 (file)
@@ -81,4 +81,37 @@ static inline void skb_clear_rxhash(struct sk_buff *skb)
 #define SET_NETNSOK    .netnsok = true,
 #endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+#ifdef CONFIG_NETFILTER
+static inline u32 skb_get_mark(struct sk_buff *skb)
+{
+       return skb->nfmark;
+}
+
+static inline void skb_set_mark(struct sk_buff *skb, u32 mark)
+{
+       skb->nfmark = mark;
+}
+#else /* CONFIG_NETFILTER */
+static inline u32 skb_get_mark(struct sk_buff *skb)
+{
+       return 0;
+}
+
+static inline void skb_set_mark(struct sk_buff *skb, u32 mark)
+{
+}
+#endif
+#else /* before 2.6.20 */
+static inline u32 skb_get_mark(struct sk_buff *skb)
+{
+       return skb->mark;
+}
+
+static inline void skb_set_mark(struct sk_buff *skb, u32 mark)
+{
+       skb->mark = mark;
+}
+#endif /* after 2.6.20 */
+
 #endif /* compat.h */
index ade9de53b8e4381d86acef71f47a884cb94cae10..f990b738a3b72f103f21b304c56352f0fdeed91f 100644 (file)
@@ -595,6 +595,13 @@ static int validate_set(const struct nlattr *a,
        case OVS_KEY_ATTR_ETHERNET:
                break;
 
+       case OVS_KEY_ATTR_SKB_MARK:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) && !defined(CONFIG_NETFILTER)
+               if (nla_get_u32(ovs_key) != 0)
+                       return -EINVAL;
+#endif
+               break;
+
        case OVS_KEY_ATTR_IPV4_TUNNEL:
                tun_key = nla_data(ovs_key);
                if (!tun_key->ipv4_dst)
@@ -826,6 +833,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 
        OVS_CB(packet)->flow = flow;
        packet->priority = flow->key.phy.priority;
+       skb_set_mark(packet, flow->key.phy.skb_mark);
 
        rcu_read_lock();
        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
index 41c624e5ef8155f269407ce28368b496a530a9c9..0c3d75fd2f8d158f15746220bc5a71819b7f956e 100644 (file)
@@ -624,6 +624,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
        if (OVS_CB(skb)->tun_key)
                memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
        key->phy.in_port = in_port;
+       key->phy.skb_mark = skb_get_mark(skb);
 
        skb_reset_mac_header(skb);
 
@@ -835,6 +836,7 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
        [OVS_KEY_ATTR_ENCAP] = -1,
        [OVS_KEY_ATTR_PRIORITY] = sizeof(u32),
        [OVS_KEY_ATTR_IN_PORT] = sizeof(u32),
+       [OVS_KEY_ATTR_SKB_MARK] = sizeof(u32),
        [OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet),
        [OVS_KEY_ATTR_VLAN] = sizeof(__be16),
        [OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16),
@@ -1024,6 +1026,15 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
        } else {
                swkey->phy.in_port = DP_MAX_PORTS;
        }
+       if (attrs & (1 << OVS_KEY_ATTR_SKB_MARK)) {
+               uint32_t mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) && !defined(CONFIG_NETFILTER)
+               if (mark != 0)
+                       return -EINVAL;
+#endif
+               swkey->phy.skb_mark = mark;
+               attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
+       }
 
        if (attrs & (1ULL << OVS_KEY_ATTR_TUN_ID) &&
            attrs & (1ULL << OVS_KEY_ATTR_IPV4_TUNNEL)) {
@@ -1203,6 +1214,7 @@ int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, int key_len, const stru
 
        flow->key.phy.in_port = DP_MAX_PORTS;
        flow->key.phy.priority = 0;
+       flow->key.phy.skb_mark = 0;
        memset(tun_key, 0, sizeof(flow->key.tun_key));
 
        nla_for_each_nested(nla, attr, rem) {
@@ -1254,6 +1266,14 @@ int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow, int key_len, const stru
                                        return -EINVAL;
                                flow->key.phy.in_port = nla_get_u32(nla);
                                break;
+
+                       case OVS_KEY_ATTR_SKB_MARK:
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) && !defined(CONFIG_NETFILTER)
+                               if (nla_get_u32(nla) != 0)
+                                       return -EINVAL;
+#endif
+                               flow->key.phy.skb_mark = nla_get_u32(nla);
+                               break;
                        }
                }
        }
@@ -1291,6 +1311,10 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
            nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port))
                goto nla_put_failure;
 
+       if (swkey->phy.skb_mark &&
+           nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, swkey->phy.skb_mark))
+               goto nla_put_failure;
+
        nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
        if (!nla)
                goto nla_put_failure;
index 54f0fcdc0f4d4a6d5a461e170fe511988a8b6ae2..3f3624ffd00a059dcb051a602206a5cf218bc940 100644 (file)
@@ -44,6 +44,7 @@ struct sw_flow_key {
        struct ovs_key_ipv4_tunnel tun_key;  /* Encapsulating tunnel key. */
        struct {
                u32     priority;       /* Packet QoS priority. */
+               u32     skb_mark;       /* SKB mark. */
                u16     in_port;        /* Input switch port (or DP_MAX_PORTS). */
        } phy;
        struct {
@@ -147,6 +148,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
  *  OVS_KEY_ATTR_TUN_ID        8    --     4     12
  *  OVS_KEY_ATTR_IPV4_TUNNEL  24    --     4     28
  *  OVS_KEY_ATTR_IN_PORT       4    --     4      8
+ *  OVS_KEY_ATTR_SKB_MARK      4    --     4      8
  *  OVS_KEY_ATTR_ETHERNET     12    --     4     16
  *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (outer VLAN ethertype)
  *  OVS_KEY_ATTR_8021Q         4    --     4      8
@@ -156,9 +158,9 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
  *  OVS_KEY_ATTR_ICMPV6        2     2     4      8
  *  OVS_KEY_ATTR_ND           28    --     4     32
  *  -------------------------------------------------
- *  total                                       184
+ *  total                                       192
  */
-#define FLOW_BUFSIZE 184
+#define FLOW_BUFSIZE 192
 
 int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
 int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
index b9518fb7b10c2dd5ddaa74c7077760fa95a5f588..a0359bba395941c491f2aa896ca7319636e030e3 100644 (file)
@@ -11,7 +11,9 @@ openvswitch (1.9.0-1) unstable; urgency=low
     - The tunneling code no longer assumes input and output keys are symmetric.
       If they are not, PMTUD needs to be disabled for tunneling to work. Note
       this only applies to flow-based keys.
-    - Datapath: Support for ipv6 set action.
+    - Datapath:
+      - Support for ipv6 set action.
+      - SKB mark matching and setting.
     - FreeBSD is now a supported platform, thanks to code contributions from
       Gaetano Catalli, Ed Maste, and Giuseppe Lettieri.
     - ovs-bugtool: New --ovs option to report only OVS related information.
index c4823d9f5dedd77e098326ca7d7273a5dc956f3d..e7d4b495d3479ee402d0c364c49ccb9c8511b1fe 100644 (file)
@@ -280,6 +280,7 @@ enum ovs_key_attr {
        OVS_KEY_ATTR_ICMPV6,    /* struct ovs_key_icmpv6 */
        OVS_KEY_ATTR_ARP,       /* struct ovs_key_arp */
        OVS_KEY_ATTR_ND,        /* struct ovs_key_nd */
+       OVS_KEY_ATTR_SKB_MARK,  /* u32 skb mark */
        OVS_KEY_ATTR_IPV4_TUNNEL,  /* struct ovs_key_ipv4_tunnel */
        OVS_KEY_ATTR_TUN_ID = 63,  /* be64 tunnel ID */
        __OVS_KEY_ATTR_MAX
index 496230e0365d2b461f39d523b43e8b1ba785e289..87eb9c1843bc2bd20f62d2438f5130c94f3ba469 100644 (file)
@@ -1387,7 +1387,7 @@ dpif_linux_vport_send(int dp_ifindex, uint32_t port_no,
     uint64_t action;
 
     ofpbuf_use_const(&packet, data, size);
-    flow_extract(&packet, 0, NULL, 0, &flow);
+    flow_extract(&packet, 0, 0, NULL, 0, &flow);
 
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
     odp_flow_key_from_flow(&key, &flow, OVSP_NONE);
index 92108df1c4614f3f602e91a4f727f9977ec75892..682dfc90a5ff21bee242e21d4fd6669dcad5cdea 100644 (file)
@@ -929,7 +929,7 @@ dpif_netdev_execute(struct dpif *dpif, const struct dpif_execute *execute)
     ofpbuf_reserve(&copy, DP_NETDEV_HEADROOM);
     ofpbuf_put(&copy, execute->packet->data, execute->packet->size);
 
-    flow_extract(&copy, 0, NULL, -1, &key);
+    flow_extract(&copy, 0, 0, NULL, -1, &key);
     error = dpif_netdev_flow_from_nlattrs(execute->key, execute->key_len,
                                           &key);
     if (!error) {
@@ -1027,7 +1027,7 @@ dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port,
     if (packet->size < ETH_HEADER_LEN) {
         return;
     }
-    flow_extract(packet, 0, NULL, port->port_no, &key);
+    flow_extract(packet, 0, 0, NULL, port->port_no, &key);
     flow = dp_netdev_lookup_flow(dp, &key);
     if (flow) {
         dp_netdev_flow_used(flow, packet);
@@ -1192,6 +1192,7 @@ execute_set_action(struct ofpbuf *packet, const struct nlattr *a)
     switch (type) {
     case OVS_KEY_ATTR_TUN_ID:
     case OVS_KEY_ATTR_PRIORITY:
+    case OVS_KEY_ATTR_SKB_MARK:
     case OVS_KEY_ATTR_IPV4_TUNNEL:
         /* not implemented */
         break;
index 7084079ea778da6dc310b9e242c9a2d0a5a9ea03..3085848dc37686396f3e964985ab3e494c1156bd 100644 (file)
@@ -335,7 +335,7 @@ invalid:
  *      present and has a correct length, and otherwise NULL.
  */
 void
-flow_extract(struct ofpbuf *packet, uint32_t skb_priority,
+flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark,
              const struct flow_tnl *tnl, uint16_t ofp_in_port,
              struct flow *flow)
 {
@@ -352,6 +352,7 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority,
     }
     flow->in_port = ofp_in_port;
     flow->skb_priority = skb_priority;
+    flow->skb_mark = skb_mark;
 
     packet->l2 = b.data;
     packet->l3 = NULL;
@@ -462,7 +463,7 @@ flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
 void
 flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
 {
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
 
     fmd->tun_id = flow->tunnel.tun_id;
     fmd->metadata = flow->metadata;
index 5f4b8cb530a0372b70e44e3af653ff18454e6ccc..804fee6016a3d73b65be72bbc95ce727a1062d77 100644 (file)
@@ -36,7 +36,7 @@ struct ofpbuf;
 /* This sequence number should be incremented whenever anything involving flows
  * or the wildcarding of flows changes.  This will cause build assertion
  * failures in places which likely need to be updated. */
-#define FLOW_WC_SEQ 17
+#define FLOW_WC_SEQ 18
 
 #define FLOW_N_REGS 8
 BUILD_ASSERT_DECL(FLOW_N_REGS <= NXM_NX_MAX_REGS);
@@ -87,6 +87,7 @@ struct flow {
     uint32_t in_port;           /* Input port. OpenFlow port number
                                    unless in DPIF code, in which case it
                                    is the datapath port number. */
+    uint32_t skb_mark;          /* Packet mark. */
     ovs_be16 vlan_tci;          /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */
     ovs_be16 dl_type;           /* Ethernet frame type. */
     ovs_be16 tp_src;            /* TCP/UDP source port. */
@@ -105,8 +106,8 @@ BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0);
 #define FLOW_U32S (sizeof(struct flow) / 4)
 
 /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
-BUILD_ASSERT_DECL(sizeof(struct flow) == sizeof(struct flow_tnl) + 144 &&
-                  FLOW_WC_SEQ == 17);
+BUILD_ASSERT_DECL(sizeof(struct flow) == sizeof(struct flow_tnl) + 152 &&
+                  FLOW_WC_SEQ == 18);
 
 /* Represents the metadata fields of struct flow. */
 struct flow_metadata {
@@ -116,8 +117,8 @@ struct flow_metadata {
     uint16_t in_port;                /* OpenFlow port or zero. */
 };
 
-void flow_extract(struct ofpbuf *, uint32_t priority, const struct flow_tnl *,
-                  uint16_t in_port, struct flow *);
+void flow_extract(struct ofpbuf *, uint32_t priority, uint32_t mark,
+                  const struct flow_tnl *, uint16_t in_port, struct flow *);
 void flow_zero_wildcards(struct flow *, const struct flow_wildcards *);
 void flow_get_metadata(const struct flow *, struct flow_metadata *);
 
index eeaa3064395eecd90522765fafd59c21fd767085..5df05f35c9b38843dc2f0c016df3a8fd5d920133 100644 (file)
@@ -539,7 +539,7 @@ process_packet_in(struct lswitch *sw, const struct ofp_header *oh)
 
     /* Extract flow data from 'opi' into 'flow'. */
     ofpbuf_use_const(&pkt, pi.packet, pi.packet_len);
-    flow_extract(&pkt, 0, NULL, pi.fmd.in_port, &flow);
+    flow_extract(&pkt, 0, 0, NULL, pi.fmd.in_port, &flow);
     flow.tunnel.tun_id = pi.fmd.tun_id;
 
     /* Choose output port. */
index 81b717348b5305f9703920ebb06235fca14a2ce7..29ee1535e0cbde3e0d66fd146f284bbe95e32b58 100644 (file)
@@ -125,6 +125,7 @@ match_init_exact(struct match *match, const struct flow *flow)
 
     match->flow = *flow;
     match->flow.skb_priority = 0;
+    match->flow.skb_mark = 0;
     memset(&match->flow.tunnel, 0, sizeof match->flow.tunnel);
     match->flow.tunnel.tun_id = tun_id;
     flow_wildcards_init_exact(&match->wc);
@@ -655,7 +656,7 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
 
     int i;
 
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
 
     if (priority != OFP_DEFAULT_PRIORITY) {
         ds_put_format(s, "priority=%u,", priority);
index 9c4088f1a65e86e404594aa3b07621c62c9c8c4b..837db8d3fd5124b16a49bdaaca471a6360bf1dd1 100644 (file)
@@ -547,7 +547,7 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match,
     int match_len;
     int i;
 
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
 
     /* Metadata. */
     if (match->wc.masks.in_port) {
index 9b0876c45982af700bce46b4607cfece67bbb51c..aa9cb4657c66c07e51bf2dcf17e5542fda33fb00 100644 (file)
@@ -93,6 +93,7 @@ ovs_key_attr_to_string(enum ovs_key_attr attr)
     case OVS_KEY_ATTR_UNSPEC: return "unspec";
     case OVS_KEY_ATTR_ENCAP: return "encap";
     case OVS_KEY_ATTR_PRIORITY: return "priority";
+    case OVS_KEY_ATTR_SKB_MARK: return "skb_mark";
     case OVS_KEY_ATTR_TUN_ID: return "tun_id";
     case OVS_KEY_ATTR_IPV4_TUNNEL: return "ipv4_tunnel";
     case OVS_KEY_ATTR_IN_PORT: return "in_port";
@@ -644,6 +645,7 @@ odp_flow_key_attr_len(uint16_t type)
     switch ((enum ovs_key_attr) type) {
     case OVS_KEY_ATTR_ENCAP: return -2;
     case OVS_KEY_ATTR_PRIORITY: return 4;
+    case OVS_KEY_ATTR_SKB_MARK: return 4;
     case OVS_KEY_ATTR_TUN_ID: return 8;
     case OVS_KEY_ATTR_IPV4_TUNNEL: return sizeof(struct ovs_key_ipv4_tunnel);
     case OVS_KEY_ATTR_IN_PORT: return 4;
@@ -754,6 +756,10 @@ format_odp_key_attr(const struct nlattr *a, struct ds *ds)
         ds_put_format(ds, "(%"PRIu32")", nl_attr_get_u32(a));
         break;
 
+    case OVS_KEY_ATTR_SKB_MARK:
+        ds_put_format(ds, "(%"PRIu32")", nl_attr_get_u32(a));
+        break;
+
     case OVS_KEY_ATTR_TUN_ID:
         ds_put_format(ds, "(%#"PRIx64")", ntohll(nl_attr_get_be64(a)));
         break;
@@ -972,6 +978,16 @@ parse_odp_key_attr(const char *s, const struct simap *port_names,
         }
     }
 
+    {
+        unsigned long long int mark;
+        int n = -1;
+
+        if (sscanf(s, "skb_mark(%lli)%n", &mark, &n) > 0 && n > 0) {
+            nl_msg_put_u32(key, OVS_KEY_ATTR_SKB_MARK, mark);
+            return n;
+        }
+    }
+
     {
         char tun_id_s[32];
         int n = -1;
@@ -1377,6 +1393,10 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow,
         nl_msg_put_be64(buf, OVS_KEY_ATTR_TUN_ID, flow->tunnel.tun_id);
     }
 
+    if (flow->skb_mark) {
+        nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, flow->skb_mark);
+    }
+
     if (odp_in_port != OVSP_NONE) {
         nl_msg_put_u32(buf, OVS_KEY_ATTR_IN_PORT, odp_in_port);
     }
@@ -1869,6 +1889,11 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_PRIORITY;
     }
 
+    if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_SKB_MARK)) {
+        flow->skb_mark = nl_attr_get_u32(attrs[OVS_KEY_ATTR_SKB_MARK]);
+        expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_SKB_MARK;
+    }
+
     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TUN_ID)) {
         flow->tunnel.tun_id = nl_attr_get_be64(attrs[OVS_KEY_ATTR_TUN_ID]);
         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_TUN_ID;
@@ -2129,6 +2154,18 @@ commit_set_priority_action(const struct flow *flow, struct flow *base,
                       &base->skb_priority, sizeof(base->skb_priority));
 }
 
+static void
+commit_set_skb_mark_action(const struct flow *flow, struct flow *base,
+                           struct ofpbuf *odp_actions)
+{
+    if (base->skb_mark == flow->skb_mark) {
+        return;
+    }
+    base->skb_mark = flow->skb_mark;
+
+    commit_set_action(odp_actions, OVS_KEY_ATTR_SKB_MARK,
+                      &base->skb_mark, sizeof(base->skb_mark));
+}
 /* If any of the flow key data that ODP actions can modify are different in
  * 'base' and 'flow', appends ODP actions to 'odp_actions' that change the flow
  * key from 'base' into 'flow', and then changes 'base' the same way. */
@@ -2142,4 +2179,5 @@ commit_odp_actions(const struct flow *flow, struct flow *base,
     commit_set_nw_action(flow, base, odp_actions);
     commit_set_port_action(flow, base, odp_actions);
     commit_set_priority_action(flow, base, odp_actions);
+    commit_set_skb_mark_action(flow, base, odp_actions);
 }
index 5cdb204109e16d394cf94841f3e35ee776c79659..9d38f33f748b827964fb377d0d276535ed23ddc6 100644 (file)
@@ -56,6 +56,7 @@ int odp_actions_from_string(const char *, const struct simap *port_names,
  *  OVS_KEY_ATTR_TUN_ID        8    --     4     12
  *  OVS_KEY_ATTR_IPV4_TUNNEL  24    --     4     28
  *  OVS_KEY_ATTR_IN_PORT       4    --     4      8
+ *  OVS_KEY_ATTR_SKB_MARK      4    --     4      8
  *  OVS_KEY_ATTR_ETHERNET     12    --     4     16
  *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (outer VLAN ethertype)
  *  OVS_KEY_ATTR_8021Q         4    --     4      8
@@ -65,12 +66,12 @@ int odp_actions_from_string(const char *, const struct simap *port_names,
  *  OVS_KEY_ATTR_ICMPV6        2     2     4      8
  *  OVS_KEY_ATTR_ND           28    --     4     32
  *  -------------------------------------------------
- *  total                                       184
+ *  total                                       192
  *
  * We include some slack space in case the calculation isn't quite right or we
  * add another field and forget to adjust this value.
  */
-#define ODPUTIL_FLOW_KEY_BYTES 200
+#define ODPUTIL_FLOW_KEY_BYTES 256
 
 /* A buffer with sufficient size and alignment to hold an nlattr-formatted flow
  * key.  An array of "struct nlattr" might not, in theory, be sufficiently
index c1b50e2c142ae7cf67883148a5b783ad9263ac05..a0f04dcb64634d734e06029a92149f553d56d692 100644 (file)
@@ -63,7 +63,7 @@ ofp_packet_to_string(const void *data, size_t len)
     struct flow flow;
 
     ofpbuf_use_const(&buf, data, len);
-    flow_extract(&buf, 0, NULL, 0, &flow);
+    flow_extract(&buf, 0, 0, NULL, 0, &flow);
     flow_format(&ds, &flow);
 
     if (buf.l7) {
index e335ff8608e70b7534c65001816bd64b5b541188..fb8d6a1eebc78a53ff36876cad872f941a3ad111 100644 (file)
@@ -85,7 +85,7 @@ ofputil_netmask_to_wcbits(ovs_be32 netmask)
 void
 ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
 {
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
 
     /* Initialize most of wc. */
     flow_wildcards_init_catchall(wc);
@@ -988,7 +988,7 @@ ofputil_usable_protocols(const struct match *match)
 {
     const struct flow_wildcards *wc = &match->wc;
 
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
+    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
 
     /* NXM, OXM, and OF1.1 support bitwise matching on ethernet addresses. */
     if (!eth_mask_is_exact(wc->masks.dl_src)
index 211ed428fb7083138dc45feada002c92419d8110..d32f6d16374f13a298d30605b9504fa07dac30d5 100644 (file)
@@ -3491,7 +3491,7 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
         if (miss->key_fitness == ODP_FIT_ERROR) {
             continue;
         }
-        flow_extract(upcall->packet, flow.skb_priority,
+        flow_extract(upcall->packet, flow.skb_priority, flow.skb_mark,
                      &flow.tunnel, flow.in_port, &miss->flow);
 
         /* Add other packets to a to-do list. */
@@ -5182,7 +5182,7 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
     struct flow flow;
     int error;
 
-    flow_extract(packet, 0, NULL, OFPP_LOCAL, &flow);
+    flow_extract(packet, 0, 0, NULL, OFPP_LOCAL, &flow);
     odp_port = vsp_realdev_to_vlandev(ofproto, ofport->odp_port,
                                       flow.vlan_tci);
     if (odp_port != ofport->odp_port) {
@@ -7214,15 +7214,17 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
             packet = ofpbuf_new(0);
             flow_compose(packet, &flow);
         }
-    } else if (argc == 6) {
-        /* ofproto/trace dpname priority tun_id in_port packet */
+    } else if (argc == 7) {
+        /* ofproto/trace dpname priority tun_id in_port mark packet */
         const char *priority_s = argv[2];
         const char *tun_id_s = argv[3];
         const char *in_port_s = argv[4];
-        const char *packet_s = argv[5];
+        const char *mark_s = argv[5];
+        const char *packet_s = argv[6];
         uint32_t in_port = atoi(in_port_s);
         ovs_be64 tun_id = htonll(strtoull(tun_id_s, NULL, 0));
         uint32_t priority = atoi(priority_s);
+        uint32_t mark = atoi(mark_s);
         const char *msg;
 
         msg = eth_from_hex(packet_s, &packet);
@@ -7236,7 +7238,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
         ds_put_cstr(&result, s);
         free(s);
 
-        flow_extract(packet, priority, NULL, in_port, &flow);
+        flow_extract(packet, priority, mark, NULL, in_port, &flow);
         flow.tunnel.tun_id = tun_id;
         initial_tci = flow.vlan_tci;
     } else {
@@ -7631,8 +7633,8 @@ ofproto_dpif_unixctl_init(void)
 
     unixctl_command_register(
         "ofproto/trace",
-        "bridge {priority tun_id in_port packet | odp_flow [-generate]}",
-        2, 5, ofproto_unixctl_trace, NULL);
+        "bridge {priority tun_id in_port mark packet | odp_flow [-generate]}",
+        2, 6, ofproto_unixctl_trace, NULL);
     unixctl_command_register("fdb/flush", "[bridge]", 0, 1,
                              ofproto_unixctl_fdb_flush, NULL);
     unixctl_command_register("fdb/show", "bridge", 1, 1,
index 3e36fe6362db14fa90fad4b6bc6feba08567ee5f..889034367187d2a08c45cbc072297c7b5b95e20e 100644 (file)
@@ -6,7 +6,7 @@ These commands manage the core OpenFlow switch implementation (called
 Lists the names of the running ofproto instances.  These are the names
 that may be used on \fBofproto/trace\fR.
 .
-.IP "\fBofproto/trace \fIswitch priority tun_id in_port packet\fR"
+.IP "\fBofproto/trace \fIswitch priority tun_id in_port mark packet\fR"
 .IQ "\fBofproto/trace \fIswitch flow \fB\-generate\fR"
 Traces the path of an imaginary packet through \fIswitch\fR.  Both
 forms require \fIswitch\fR, the switch on which the packet arrived
@@ -21,6 +21,8 @@ The tunnel ID on which the packet arrived.  Use
 .IP "\fIin_port\fR"
 The OpenFlow port on which the packet arrived.  Use \fB65534\fR if the
 packet arrived on \fBOFPP_LOCAL\fR, the local port.
+.IP "\fImark\fR"
+SKB mark of the packet. Use \fB0\fR if Netfilter marks are not used.
 .IP "\fIpacket\fR"
 A sequence of hex digits specifying the packet's contents.  An
 Ethernet frame is at least 14 bytes long, so there must be at least 28
index 8bc9b590c50a3e44bc73fa4a7396b6393786ac64..dabb590d3e55027219feb9fca6275291d91e9ffc 100644 (file)
@@ -2171,7 +2171,7 @@ rule_execute(struct rule *rule, uint16_t in_port, struct ofpbuf *packet)
 
     assert(ofpbuf_headroom(packet) >= sizeof(struct ofp_packet_in));
 
-    flow_extract(packet, 0, NULL, in_port, &flow);
+    flow_extract(packet, 0, 0, NULL, in_port, &flow);
     return rule->ofproto->ofproto_class->rule_execute(rule, &flow, packet);
 }
 
@@ -2360,7 +2360,7 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
     }
 
     /* Verify actions against packet, then send packet if successful. */
-    flow_extract(payload, 0, NULL, po.in_port, &flow);
+    flow_extract(payload, 0, 0, NULL, po.in_port, &flow);
     error = ofpacts_check(po.ofpacts, po.ofpacts_len, &flow, p->max_ports);
     if (!error) {
         error = p->ofproto_class->packet_out(p, payload, &flow,
index 8f5676d6f3b0bc02c709e11ca9e53ac698dc6873..a5f6dbe58d0b0fd600879df2303166352ec0ab11 100644 (file)
@@ -24,6 +24,7 @@ in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(target=::3,tll=00:0a:0b:0c:0d:0e)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(target=::3,sll=00:05:06:07:08:09,tll=00:0a:0b:0c:0d:0e)
 in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0806),arp(sip=1.2.3.4,tip=5.6.7.8,op=1,sha=00:0f:10:11:12:13,tha=00:14:15:16:17:18)
+skb_mark(17185),in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=58,tclass=0,hlimit=128,frag=no),icmpv6(type=136,code=0),nd(target=::3,sll=00:05:06:07:08:09,tll=00:0a:0b:0c:0d:0e)
 ])
 
 (echo '# Valid forms without tun_id or VLAN header.'
index a40709a125360e1eb7ab379aa1488d33879408ed..b4dedeeb9a031645680708f5201841fa01ad4270 100644 (file)
@@ -68,7 +68,7 @@ main(int argc OVS_UNUSED, char *argv[])
             ovs_fatal(retval, "error reading pcap file");
         }
 
-        flow_extract(packet, 0, NULL, 1, &flow);
+        flow_extract(packet, 0, 0, NULL, 1, &flow);
         match_init_exact(&match, &flow);
         ofputil_match_to_ofp10_match(&match, &extracted_match);