ovs-brcompatd: Fix uninitialized br_vlan variable in handle_fdb_query_cmd().
[openvswitch] / datapath / tunnel.c
index a7d4943781975a1548589aa62412e72d32e50db7..32632233659ee7cca37cb49194987fe2dd866c17 100644 (file)
@@ -186,7 +186,7 @@ struct port_lookup_key {
  * Modifies 'target' to store the rcu_dereferenced pointer that was used to do
  * the comparision.
  */
-static int port_cmp(const struct tbl_node *node, void *target)
+static int port_cmp(const struct tbl_node *node, void *target, int unused)
 {
        const struct tnl_vport *tnl_vport = tnl_vport_table_cast(node);
        struct port_lookup_key *lookup = target;
@@ -337,7 +337,8 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
                lookup.tunnel_type = tunnel_type & ~TNL_T_KEY_MATCH;
 
                if (key_local_remote_ports) {
-                       tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+                       tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+                                             port_hash(&lookup), port_cmp);
                        if (tbl_node)
                                goto found;
                }
@@ -345,7 +346,8 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
                if (key_remote_ports) {
                        lookup.saddr = 0;
 
-                       tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+                       tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+                                             port_hash(&lookup), port_cmp);
                        if (tbl_node)
                                goto found;
 
@@ -358,7 +360,8 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
                lookup.tunnel_type = tunnel_type & ~TNL_T_KEY_EXACT;
 
                if (local_remote_ports) {
-                       tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+                       tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+                                             port_hash(&lookup), port_cmp);
                        if (tbl_node)
                                goto found;
                }
@@ -366,7 +369,8 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key,
                if (remote_ports) {
                        lookup.saddr = 0;
 
-                       tbl_node = tbl_lookup(table, &lookup, port_hash(&lookup), port_cmp);
+                       tbl_node = tbl_lookup(table, &lookup, sizeof(lookup),
+                                             port_hash(&lookup), port_cmp);
                        if (tbl_node)
                                goto found;
                }
@@ -725,8 +729,9 @@ static bool check_mtu(struct sk_buff *skb,
                      const struct tnl_mutable_config *mutable,
                      const struct rtable *rt, __be16 *frag_offp)
 {
+       bool df_inherit = mutable->flags & TNL_F_DF_INHERIT;
        bool pmtud = mutable->flags & TNL_F_PMTUD;
-       __be16 frag_off = 0;
+       __be16 frag_off = mutable->flags & TNL_F_DF_DEFAULT ? htons(IP_DF) : 0;
        int mtu = 0;
        unsigned int packet_length = skb->len - ETH_HLEN;
 
@@ -738,8 +743,6 @@ static bool check_mtu(struct sk_buff *skb,
        if (pmtud) {
                int vlan_header = 0;
 
-               frag_off = htons(IP_DF);
-
                /* The tag needs to go in packet regardless of where it
                 * currently is, so subtract it from the MTU.
                 */
@@ -756,7 +759,8 @@ static bool check_mtu(struct sk_buff *skb,
        if (skb->protocol == htons(ETH_P_IP)) {
                struct iphdr *iph = ip_hdr(skb);
 
-               frag_off |= iph->frag_off & htons(IP_DF);
+               if (df_inherit)
+                       frag_off = iph->frag_off & htons(IP_DF);
 
                if (pmtud && iph->frag_off & htons(IP_DF)) {
                        mtu = max(mtu, IP_MIN_MTU);
@@ -769,8 +773,10 @@ static bool check_mtu(struct sk_buff *skb,
        }
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        else if (skb->protocol == htons(ETH_P_IPV6)) {
-               /* IPv6 requires PMTUD if the packet is above the minimum MTU. */
-               if (packet_length > IPV6_MIN_MTU)
+               /* IPv6 requires end hosts to do fragmentation
+                * if the packet is above the minimum MTU.
+                */
+               if (df_inherit && packet_length > IPV6_MIN_MTU)
                        frag_off = htons(IP_DF);
 
                if (pmtud) {
@@ -804,7 +810,7 @@ static void create_tunnel_header(const struct vport *vport,
        iph->saddr      = rt->rt_src;
        iph->ttl        = mutable->ttl;
        if (!iph->ttl)
-               iph->ttl = dst_metric(&rt_dst(rt), RTAX_HOPLIMIT);
+               iph->ttl = ip4_dst_hoplimit(&rt_dst(rt));
 
        tnl_vport->tnl_ops->build_header(vport, mutable, iph + 1);
 }
@@ -938,6 +944,7 @@ static struct tnl_cache *build_cache(struct vport *vport,
                struct sk_buff *skb;
                bool is_frag;
                int err;
+               int flow_key_len;
 
                dst_vport = internal_dev_get_vport(rt_dst(rt).dev);
                if (!dst_vport)
@@ -950,14 +957,16 @@ static struct tnl_cache *build_cache(struct vport *vport,
                __skb_put(skb, cache->len);
                memcpy(skb->data, get_cached_header(cache), cache->len);
 
-               err = flow_extract(skb, dst_vport->port_no, &flow_key, &is_frag);
+               err = flow_extract(skb, dst_vport->port_no, &flow_key,
+                                  &flow_key_len, &is_frag);
 
                kfree_skb(skb);
                if (err || is_frag)
                        goto done;
 
                flow_node = tbl_lookup(rcu_dereference(dst_vport->dp->table),
-                                      &flow_key, flow_hash(&flow_key),
+                                      &flow_key, flow_key_len,
+                                      flow_hash(&flow_key, flow_key_len),
                                       flow_cmp);
                if (flow_node) {
                        struct sw_flow *flow = flow_cast(flow_node);
@@ -991,6 +1000,7 @@ static struct rtable *find_route(struct vport *vport,
                return cur_cache->rt;
        } else {
                struct rtable *rt;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
                struct flowi fl = { .nl_u = { .ip4_u =
                                              { .daddr = mutable->daddr,
                                                .saddr = mutable->saddr,
@@ -999,6 +1009,16 @@ static struct rtable *find_route(struct vport *vport,
 
                if (unlikely(ip_route_output_key(&init_net, &rt, &fl)))
                        return NULL;
+#else
+               struct flowi4 fl = { .daddr = mutable->daddr,
+                                    .saddr = mutable->saddr,
+                                    .flowi4_tos = tos,
+                                    .flowi4_proto = tnl_vport->tnl_ops->ipproto };
+
+               rt = ip_route_output_key(&init_net, &fl);
+               if (IS_ERR(rt))
+                       return NULL;
+#endif
 
                if (likely(tos == mutable->tos))
                        *cache = build_cache(vport, mutable, rt);
@@ -1233,7 +1253,7 @@ int tnl_send(struct vport *vport, struct sk_buff *skb)
        /* TTL */
        ttl = mutable->ttl;
        if (!ttl)
-               ttl = dst_metric(&rt_dst(rt), RTAX_HOPLIMIT);
+               ttl = ip4_dst_hoplimit(&rt_dst(rt));
 
        if (mutable->flags & TNL_F_TTL_INHERIT) {
                if (skb->protocol == htons(ETH_P_IP))