X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Ftunnel.c;h=c2133bb4722a15b8f378f539d49d4022a51eecf2;hb=e0edde6fee279cdbbf3c179f5f50adaf0c7c7f1e;hp=41907b95e039e0699421e42fb86a96bbd7f51ea7;hpb=850b6b3b9f8c38b42e315c2c07d232a33b82da3e;p=sliver-openvswitch.git diff --git a/datapath/tunnel.c b/datapath/tunnel.c index 41907b95e..c2133bb47 100644 --- a/datapath/tunnel.c +++ b/datapath/tunnel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2011 Nicira Networks. + * Copyright (c) 2007-2012 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 @@ -16,6 +16,8 @@ * 02110-1301, USA */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -109,7 +111,7 @@ static unsigned int multicast_ports __read_mostly; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) static struct hh_cache *rt_hh(struct rtable *rt) { - struct neighbour *neigh = dst_get_neighbour(&rt->dst); + struct neighbour *neigh = dst_get_neighbour_noref(&rt->dst); if (!neigh || !(neigh->nud_state & NUD_CONNECTED) || !neigh->hh.hh_len) return NULL; @@ -169,7 +171,7 @@ static void free_mutable_rtnl(struct tnl_mutable_config *mutable) ASSERT_RTNL(); if (ipv4_is_multicast(mutable->key.daddr) && mutable->mlink) { struct in_device *in_dev; - in_dev = inetdev_by_index(&init_net, mutable->mlink); + in_dev = inetdev_by_index(port_key_get_net(&mutable->key), mutable->mlink); if (in_dev) ip_mc_dec_group(in_dev, mutable->key.daddr); } @@ -299,14 +301,15 @@ static struct vport *port_table_lookup(struct port_lookup_key *key, return NULL; } -struct vport *ovs_tnl_find_port(__be32 saddr, __be32 daddr, __be64 key, - int tunnel_type, +struct vport *ovs_tnl_find_port(struct net *net, __be32 saddr, __be32 daddr, + __be64 key, int tunnel_type, const struct tnl_mutable_config **mutable) { struct port_lookup_key lookup; struct vport *vport; bool is_multicast = ipv4_is_multicast(saddr); + port_key_set_net(&lookup, net); lookup.saddr = saddr; lookup.daddr = daddr; @@ -538,6 +541,7 @@ static bool ipv6_should_icmp(struct sk_buff *skb) int addr_type; int payload_off = (u8 *)(old_ipv6h + 1) - skb->data; u8 nexthdr = ipv6_hdr(skb)->nexthdr; + __be16 frag_off; /* Check source address is valid. */ addr_type = ipv6_addr_type(&old_ipv6h->saddr); @@ -549,7 +553,7 @@ static bool ipv6_should_icmp(struct sk_buff *skb) return false; /* Don't respond to ICMP error messages. */ - payload_off = ipv6_skip_exthdr(skb, payload_off, &nexthdr); + payload_off = ipv6_skip_exthdr(skb, payload_off, &nexthdr, &frag_off); if (payload_off < 0) return false; @@ -587,8 +591,8 @@ static void ipv6_build_icmp(struct sk_buff *skb, struct sk_buff *nskb, + payload_length); ipv6h->nexthdr = NEXTHDR_ICMP; ipv6h->hop_limit = IPV6_DEFAULT_HOPLIMIT; - ipv6_addr_copy(&ipv6h->daddr, &old_ipv6h->saddr); - ipv6_addr_copy(&ipv6h->saddr, &old_ipv6h->daddr); + ipv6h->daddr = old_ipv6h->saddr; + ipv6h->saddr = old_ipv6h->daddr; /* ICMPv6 */ icmp6h->icmp6_type = ICMPV6_PKT_TOOBIG; @@ -810,6 +814,13 @@ static void *get_cached_header(const struct tnl_cache *cache) return (void *)cache + ALIGN(sizeof(struct tnl_cache), CACHE_DATA_ALIGN); } +#ifdef HAVE_RT_GENID +static inline int rt_genid(struct net *net) +{ + return atomic_read(&net->ipv4.rt_genid); +} +#endif + static bool check_cache_valid(const struct tnl_cache *cache, const struct tnl_mutable_config *mutable) { @@ -824,7 +835,7 @@ static bool check_cache_valid(const struct tnl_cache *cache, time_before(jiffies, cache->expiration) && #endif #ifdef HAVE_RT_GENID - atomic_read(&init_net.ipv4.rt_genid) == cache->rt->rt_genid && + rt_genid(dev_net(rt_dst(cache->rt).dev)) == cache->rt->rt_genid && #endif #ifdef HAVE_HH_SEQ hh->hh_lock.sequence == cache->hh_seq && @@ -857,7 +868,7 @@ static void cache_cleaner(struct work_struct *work) for (i = 0; i < PORT_TABLE_SIZE; i++) { struct hlist_node *n; struct hlist_head *bucket; - struct tnl_vport *tnl_vport; + struct tnl_vport *tnl_vport; bucket = &port_table[i]; hlist_for_each_entry_rcu(tnl_vport, n, bucket, hash_node) @@ -999,7 +1010,7 @@ static struct rtable *__find_route(const struct tnl_mutable_config *mutable, .proto = ipproto }; struct rtable *rt; - if (unlikely(ip_route_output_key(&init_net, &rt, &fl))) + if (unlikely(ip_route_output_key(port_key_get_net(&mutable->key), &rt, &fl))) return ERR_PTR(-EADDRNOTAVAIL); return rt; @@ -1009,7 +1020,7 @@ static struct rtable *__find_route(const struct tnl_mutable_config *mutable, .flowi4_tos = tos, .flowi4_proto = ipproto }; - return ip_route_output_key(&init_net, &fl); + return ip_route_output_key(port_key_get_net(&mutable->key), &fl); #endif } @@ -1359,7 +1370,8 @@ static const struct nla_policy tnl_policy[OVS_TUNNEL_ATTR_MAX + 1] = { /* Sets OVS_TUNNEL_ATTR_* fields in 'mutable', which must initially be * zeroed. */ -static int tnl_set_config(struct nlattr *options, const struct tnl_ops *tnl_ops, +static int tnl_set_config(struct net *net, struct nlattr *options, + const struct tnl_ops *tnl_ops, const struct vport *cur_vport, struct tnl_mutable_config *mutable) { @@ -1380,6 +1392,7 @@ static int tnl_set_config(struct nlattr *options, const struct tnl_ops *tnl_ops, mutable->flags = nla_get_u32(a[OVS_TUNNEL_ATTR_FLAGS]) & TNL_F_PUBLIC; + port_key_set_net(&mutable->key, net); mutable->key.daddr = nla_get_be32(a[OVS_TUNNEL_ATTR_DST_IPV4]); if (a[OVS_TUNNEL_ATTR_SRC_IPV4]) { if (ipv4_is_multicast(mutable->key.daddr)) @@ -1471,7 +1484,8 @@ struct vport *ovs_tnl_create(const struct vport_parms *parms, get_random_bytes(&initial_frag_id, sizeof(int)); atomic_set(&tnl_vport->frag_id, initial_frag_id); - err = tnl_set_config(parms->options, tnl_ops, NULL, mutable); + err = tnl_set_config(ovs_dp_get_net(parms->dp), parms->options, tnl_ops, + NULL, mutable); if (err) goto error_free_mutable; @@ -1515,7 +1529,8 @@ int ovs_tnl_set_options(struct vport *vport, struct nlattr *options) memcpy(mutable->eth_addr, old_mutable->eth_addr, ETH_ALEN); /* Parse the others configured by userspace. */ - err = tnl_set_config(options, tnl_vport->tnl_ops, vport, mutable); + err = tnl_set_config(ovs_dp_get_net(vport->dp), options, tnl_vport->tnl_ops, + vport, mutable); if (err) goto error_free; @@ -1538,19 +1553,24 @@ int ovs_tnl_get_options(const struct vport *vport, struct sk_buff *skb) const struct tnl_vport *tnl_vport = tnl_vport_priv(vport); const struct tnl_mutable_config *mutable = rcu_dereference_rtnl(tnl_vport->mutable); - NLA_PUT_U32(skb, OVS_TUNNEL_ATTR_FLAGS, mutable->flags & TNL_F_PUBLIC); - NLA_PUT_BE32(skb, OVS_TUNNEL_ATTR_DST_IPV4, mutable->key.daddr); - - if (!(mutable->flags & TNL_F_IN_KEY_MATCH)) - NLA_PUT_BE64(skb, OVS_TUNNEL_ATTR_IN_KEY, mutable->key.in_key); - if (!(mutable->flags & TNL_F_OUT_KEY_ACTION)) - NLA_PUT_BE64(skb, OVS_TUNNEL_ATTR_OUT_KEY, mutable->out_key); - if (mutable->key.saddr) - NLA_PUT_BE32(skb, OVS_TUNNEL_ATTR_SRC_IPV4, mutable->key.saddr); - if (mutable->tos) - NLA_PUT_U8(skb, OVS_TUNNEL_ATTR_TOS, mutable->tos); - if (mutable->ttl) - NLA_PUT_U8(skb, OVS_TUNNEL_ATTR_TTL, mutable->ttl); + if (nla_put_u32(skb, OVS_TUNNEL_ATTR_FLAGS, + mutable->flags & TNL_F_PUBLIC) || + nla_put_be32(skb, OVS_TUNNEL_ATTR_DST_IPV4, mutable->key.daddr)) + goto nla_put_failure; + + if (!(mutable->flags & TNL_F_IN_KEY_MATCH) && + nla_put_be64(skb, OVS_TUNNEL_ATTR_IN_KEY, mutable->key.in_key)) + goto nla_put_failure; + if (!(mutable->flags & TNL_F_OUT_KEY_ACTION) && + nla_put_be64(skb, OVS_TUNNEL_ATTR_OUT_KEY, mutable->out_key)) + goto nla_put_failure; + if (mutable->key.saddr && + nla_put_be32(skb, OVS_TUNNEL_ATTR_SRC_IPV4, mutable->key.saddr)) + goto nla_put_failure; + if (mutable->tos && nla_put_u8(skb, OVS_TUNNEL_ATTR_TOS, mutable->tos)) + goto nla_put_failure; + if (mutable->ttl && nla_put_u8(skb, OVS_TUNNEL_ATTR_TTL, mutable->ttl)) + goto nla_put_failure; return 0; @@ -1623,7 +1643,7 @@ int ovs_tnl_init(void) int i; port_table = kmalloc(PORT_TABLE_SIZE * sizeof(struct hlist_head *), - GFP_KERNEL); + GFP_KERNEL); if (!port_table) return -ENOMEM; @@ -1635,19 +1655,5 @@ int ovs_tnl_init(void) void ovs_tnl_exit(void) { - int i; - - for (i = 0; i < PORT_TABLE_SIZE; i++) { - struct tnl_vport *tnl_vport; - struct hlist_head *hash_head; - struct hlist_node *n; - - hash_head = &port_table[i]; - hlist_for_each_entry(tnl_vport, n, hash_head, hash_node) { - BUG(); - goto out; - } - } -out: kfree(port_table); }