netdev-dpdk: fix mbuf leaks
[cascardo/ovs.git] / datapath / flow.h
index 69664cd..c0b628a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2014 Nicira, Inc.
+ * Copyright (c) 2007-2015 Nicira, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
 #include <linux/jiffies.h>
 #include <linux/time.h>
 #include <linux/flex_array.h>
-
 #include <net/inet_ecn.h>
 #include <net/ip_tunnels.h>
+#include <net/dst_metadata.h>
 
 struct sk_buff;
 
-/* Used to memset ovs_key_ipv4_tunnel padding. */
-#define OVS_TUNNEL_KEY_SIZE                                    \
-        (offsetof(struct ovs_key_ipv4_tunnel, ipv4_ttl) +      \
-         FIELD_SIZEOF(struct ovs_key_ipv4_tunnel, ipv4_ttl))
-
-struct ovs_key_ipv4_tunnel {
-       __be64 tun_id;
-       __be32 ipv4_src;
-       __be32 ipv4_dst;
-       __be16 tun_flags;
-       u8   ipv4_tos;
-       u8   ipv4_ttl;
-} __packed __aligned(4); /* Minimize padding. */
-
-struct ovs_tunnel_info {
-       struct ovs_key_ipv4_tunnel tunnel;
-       struct geneve_opt *options;
-       u8 options_len;
-};
-
 /* Store options at the end of the array if they are less than the
  * maximum size. This allows us to get the benefits of variable length
  * matching for small options.
  */
-#define GENEVE_OPTS(flow_key, opt_len) (struct geneve_opt *) \
-                                       ((flow_key)->tun_opts + \
-                                       FIELD_SIZEOF(struct sw_flow_key, tun_opts) - \
-                                          opt_len)
-
-static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
-                                        const struct iphdr *iph, __be64 tun_id,
-                                        __be16 tun_flags,
-                                        struct geneve_opt *opts,
-                                        u8 opts_len)
-{
-       tun_info->tunnel.tun_id = tun_id;
-       tun_info->tunnel.ipv4_src = iph->saddr;
-       tun_info->tunnel.ipv4_dst = iph->daddr;
-       tun_info->tunnel.ipv4_tos = iph->tos;
-       tun_info->tunnel.ipv4_ttl = iph->ttl;
-       tun_info->tunnel.tun_flags = tun_flags;
-
-       /* clear struct padding. */
-       memset((unsigned char *) &tun_info->tunnel + OVS_TUNNEL_KEY_SIZE, 0,
-              sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
-
-       tun_info->options = opts;
-       tun_info->options_len = opts_len;
-}
+#define TUN_METADATA_OFFSET(opt_len) \
+       (FIELD_SIZEOF(struct sw_flow_key, tun_opts) - opt_len)
+#define TUN_METADATA_OPTS(flow_key, opt_len) \
+       ((void *)((flow_key)->tun_opts + TUN_METADATA_OFFSET(opt_len)))
+
+struct ovs_tunnel_info {
+       struct metadata_dst     *tun_dst;
+};
+
+#define OVS_SW_FLOW_KEY_METADATA_SIZE                  \
+       (offsetof(struct sw_flow_key, recirc_id) +      \
+       FIELD_SIZEOF(struct sw_flow_key, recirc_id))
 
 struct sw_flow_key {
        u8 tun_opts[255];
        u8 tun_opts_len;
-       struct ovs_key_ipv4_tunnel tun_key;  /* Encapsulating tunnel key. */
+       struct ip_tunnel_key tun_key;  /* Encapsulating tunnel key. */
        struct {
                u32     priority;       /* Packet QoS priority. */
                u32     skb_mark;       /* SKB mark. */
@@ -106,13 +73,13 @@ struct sw_flow_key {
        } eth;
        union {
                struct {
-                       __be32 top_lse;         /* top label stack entry */
+                       __be32 top_lse; /* top label stack entry */
                } mpls;
                struct {
-                       u8     proto;           /* IP protocol or lower 8 bits of ARP opcode. */
-                       u8     tos;                 /* IP ToS. */
-                       u8     ttl;                 /* IP TTL/hop limit. */
-                       u8     frag;            /* One of OVS_FRAG_TYPE_*. */
+                       u8     proto;   /* IP protocol or lower 8 bits of ARP opcode. */
+                       u8     tos;         /* IP ToS. */
+                       u8     ttl;         /* IP TTL/hop limit. */
+                       u8     frag;    /* One of OVS_FRAG_TYPE_*. */
                } ip;
        };
        struct {
@@ -144,6 +111,14 @@ struct sw_flow_key {
                        } nd;
                } ipv6;
        };
+       struct {
+               /* Connection tracking fields. */
+               u16 zone;
+               u32 mark;
+               u8 state;
+               struct ovs_key_ct_labels labels;
+       } ct;
+
 } __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
 
 struct sw_flow_key_range {
@@ -164,8 +139,19 @@ struct sw_flow_match {
        struct sw_flow_mask *mask;
 };
 
+#define MAX_UFID_LENGTH 16 /* 128 bits */
+
+struct sw_flow_id {
+       u32 ufid_len;
+       union {
+               u32 ufid[MAX_UFID_LENGTH / 4];
+               struct sw_flow_key *unmasked_key;
+       };
+};
+
 struct sw_flow_actions {
        struct rcu_head rcu;
+       size_t orig_len;        /* From flow_cmd_new netlink actions size */
        u32 actions_len;
        struct nlattr actions[];
 };
@@ -180,13 +166,15 @@ struct flow_stats {
 
 struct sw_flow {
        struct rcu_head rcu;
-       struct hlist_node hash_node[2];
-       u32 hash;
+       struct {
+               struct hlist_node node[2];
+               u32 hash;
+       } flow_table, ufid_table;
        int stats_last_writer;          /* NUMA-node id of the last writer on
                                         * 'stats[0]'.
                                         */
        struct sw_flow_key key;
-       struct sw_flow_key unmasked_key;
+       struct sw_flow_id id;
        struct sw_flow_mask *mask;
        struct sw_flow_actions __rcu *sf_acts;
        struct flow_stats __rcu *stats[]; /* One for each NUMA node.  First one
@@ -210,17 +198,31 @@ struct arp_eth_header {
        unsigned char       ar_tip[4];          /* target IP address        */
 } __packed;
 
+static inline bool ovs_identifier_is_ufid(const struct sw_flow_id *sfid)
+{
+       return sfid->ufid_len;
+}
+
+static inline bool ovs_identifier_is_key(const struct sw_flow_id *sfid)
+{
+       return !ovs_identifier_is_ufid(sfid);
+}
+
 void ovs_flow_stats_update(struct sw_flow *, __be16 tcp_flags,
-                          struct sk_buff *);
+                          const struct sk_buff *);
 void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
                        unsigned long *used, __be16 *tcp_flags);
 void ovs_flow_stats_clear(struct sw_flow *);
 u64 ovs_flow_used_time(unsigned long flow_jiffies);
 
-int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key);
+/* Update the non-metadata part of the flow key using skb. */
+int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
+int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
+                        struct sk_buff *skb,
+                        struct sw_flow_key *key);
 /* Extract key from packet coming from userspace. */
-int ovs_flow_key_extract_userspace(const struct nlattr *attr,
+int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
                                   struct sk_buff *skb,
-                                  struct sw_flow_key *key);
+                                  struct sw_flow_key *key, bool log);
 
 #endif /* flow.h */