X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Ftunnel.c;h=bd63da5555d849990d64e79ac9b2c35291cf9917;hb=7aaeab4df24b7e9460705b1dad1010eef0354c50;hp=0cc06073a66a01b2e68e45bcc3bac996e8188a94;hpb=c405d282fb7dda49b0aaac12a30121e5f2762b16;p=sliver-openvswitch.git diff --git a/datapath/tunnel.c b/datapath/tunnel.c index 0cc06073a..bd63da555 100644 --- a/datapath/tunnel.c +++ b/datapath/tunnel.c @@ -37,12 +37,6 @@ #include "vlan.h" #include "vport.h" -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) -#define rt_dst(rt) (rt->dst) -#else -#define rt_dst(rt) (rt->u.dst) -#endif - /** * ovs_tnl_rcv - ingress point for generic tunnel code * @@ -58,7 +52,8 @@ * - skb->csum does not include the inner Ethernet header. * - The layer pointers are undefined. */ -void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb) +void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb, + struct ovs_key_ipv4_tunnel *tun_key) { struct ethhdr *eh; @@ -81,12 +76,12 @@ void ovs_tnl_rcv(struct vport *vport, struct sk_buff *skb) return; } - ovs_vport_receive(vport, skb); + ovs_vport_receive(vport, skb, tun_key); } -static struct rtable *find_route(struct net *net, - __be32 *saddr, __be32 daddr, u8 ipproto, - u8 tos, u32 skb_mark) +struct rtable *find_route(struct net *net, + __be32 *saddr, __be32 daddr, u8 ipproto, + u8 tos, u32 skb_mark) { struct rtable *rt; /* Tunnel configuration keeps DSCP part of TOS bits, But Linux @@ -149,16 +144,22 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb) if (skb_is_gso(skb)) { struct sk_buff *nskb; + char cb[sizeof(skb->cb)]; + + memcpy(cb, skb->cb, sizeof(cb)); nskb = __skb_gso_segment(skb, 0, false); if (IS_ERR(nskb)) { - kfree_skb(skb); err = PTR_ERR(nskb); goto error; } consume_skb(skb); skb = nskb; + while (nskb) { + memcpy(nskb->cb, cb, sizeof(cb)); + nskb = nskb->next; + } } else if (get_ip_summed(skb) == OVS_CSUM_PARTIAL) { /* Pages aren't locked and could change at any time. * If this happens after we compute the checksum, the @@ -168,20 +169,18 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb) if (unlikely(need_linearize(skb))) { err = __skb_linearize(skb); if (unlikely(err)) - goto error_free; + goto error; } err = skb_checksum_help(skb); if (unlikely(err)) - goto error_free; + goto error; } set_ip_summed(skb, OVS_CSUM_NONE); return skb; -error_free: - kfree_skb(skb); error: return ERR_PTR(err); } @@ -194,7 +193,9 @@ u16 ovs_tnl_get_src_port(struct sk_buff *skb) int low; int high; unsigned int range; - u32 hash = OVS_CB(skb)->flow->hash; + struct sw_flow_key *pkt_key = OVS_CB(skb)->pkt_key; + u32 hash = jhash2((const u32 *)pkt_key, + sizeof(*pkt_key) / sizeof(u32), 0); inet_get_local_port_range(&low, &high); range = (high - low) + 1; @@ -211,6 +212,8 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb, struct rtable *rt; __be32 saddr; int sent_len = 0; + int err; + struct sk_buff *nskb; /* Route lookup */ saddr = OVS_CB(skb)->tun_key->ipv4_src; @@ -220,8 +223,10 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb, ipproto, OVS_CB(skb)->tun_key->ipv4_tos, skb_get_mark(skb)); - if (IS_ERR(rt)) - goto error_free; + if (IS_ERR(rt)) { + err = PTR_ERR(rt); + goto error; + } tunnel_hlen += sizeof(struct iphdr); @@ -230,7 +235,6 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb, + (vlan_tx_tag_present(skb) ? VLAN_HLEN : 0); if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) { - int err; int head_delta = SKB_DATA_ALIGN(min_headroom - skb_headroom(skb) + 16); @@ -242,11 +246,12 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb, } /* Offloading */ - skb = handle_offloads(skb); - if (IS_ERR(skb)) { - skb = NULL; + nskb = handle_offloads(skb); + if (IS_ERR(nskb)) { + err = PTR_ERR(nskb); goto err_free_rt; } + skb = nskb; /* Reset SKB */ nf_reset(skb); @@ -258,7 +263,6 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb, struct sk_buff *next_skb = skb->next; struct iphdr *iph; int frag_len; - int err; skb->next = NULL; @@ -288,7 +292,7 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb, iph->tos = OVS_CB(skb)->tun_key->ipv4_tos; iph->ttl = OVS_CB(skb)->tun_key->ipv4_ttl; iph->frag_off = OVS_CB(skb)->tun_key->tun_flags & - OVS_TNL_F_DONT_FRAGMENT ? htons(IP_DF) : 0; + TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; /* * Allow our local IP stack to fragment the outer packet even * if the DF bit is set as a last resort. We also need to @@ -311,15 +315,10 @@ next: skb = next_skb; } - if (unlikely(sent_len == 0)) - ovs_vport_record_error(vport, VPORT_E_TX_DROPPED); - return sent_len; err_free_rt: ip_rt_put(rt); -error_free: - kfree_skb(skb); - ovs_vport_record_error(vport, VPORT_E_TX_ERROR); - return sent_len; +error: + return err; }