datapath: Unify vport error stats handling.
authorPravin B Shelar <pshelar@nicira.com>
Mon, 6 May 2013 17:31:01 +0000 (10:31 -0700)
committerPravin B Shelar <pshelar@nicira.com>
Mon, 6 May 2013 17:31:01 +0000 (10:31 -0700)
Following patch changes vport->send return type so that vport
layer can do error accounting.

Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
datapath/tunnel.c
datapath/vport-gre.c
datapath/vport-lisp.c
datapath/vport-netdev.c
datapath/vport-vxlan.c
datapath/vport.c
datapath/vport.h

index 0cc0607..8cf1c16 100644 (file)
@@ -152,7 +152,6 @@ static struct sk_buff *handle_offloads(struct sk_buff *skb)
 
                nskb = __skb_gso_segment(skb, 0, false);
                if (IS_ERR(nskb)) {
-                       kfree_skb(skb);
                        err = PTR_ERR(nskb);
                        goto error;
                }
@@ -168,20 +167,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);
 }
@@ -211,6 +208,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 +219,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 +231,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 +242,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 +259,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;
 
@@ -311,15 +311,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;
 }
index 0c7ae57..53c6b29 100644 (file)
@@ -356,11 +356,8 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
 {
        int hlen;
 
-       if (unlikely(!OVS_CB(skb)->tun_key)) {
-               kfree_skb(skb);
-               ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
-               return 0;
-       }
+       if (unlikely(!OVS_CB(skb)->tun_key))
+               return -EINVAL;
 
        hlen = gre_hdr_len(OVS_CB(skb)->tun_key);
        return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre_build_header);
@@ -412,11 +409,8 @@ static int gre64_tnl_send(struct vport *vport, struct sk_buff *skb)
 {
        int hlen;
 
-       if (unlikely(!OVS_CB(skb)->tun_key)) {
-               ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
-               kfree_skb(skb);
-               return 0;
-       }
+       if (unlikely(!OVS_CB(skb)->tun_key))
+               return -EINVAL;
 
        hlen = gre64_hdr_len(OVS_CB(skb)->tun_key);
        return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre64_build_header);
index d45a4cc..554495d 100644 (file)
@@ -365,10 +365,8 @@ static int lisp_tnl_send(struct vport *vport, struct sk_buff *skb)
        int tnl_len;
        int network_offset = skb_network_offset(skb);
 
-       if (unlikely(!OVS_CB(skb)->tun_key)) {
-               ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
-               goto free;
-       }
+       if (unlikely(!OVS_CB(skb)->tun_key))
+               return -EINVAL;
 
        /* We only encapsulate IPv4 and IPv6 packets */
        switch (skb->protocol) {
@@ -380,13 +378,8 @@ static int lisp_tnl_send(struct vport *vport, struct sk_buff *skb)
                                LISP_HLEN, lisp_build_header);
                return tnl_len > 0 ? tnl_len + network_offset : tnl_len;
        default:
-               ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
-               goto free;
+               return 0;
        }
-
-free:
-       kfree_skb(skb);
-       return 0;
 }
 
 static const char *lisp_get_name(const struct vport *vport)
index 4558079..55592f9 100644 (file)
@@ -291,7 +291,7 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
                net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
                                     netdev_vport->dev->name,
                                     packet_length(skb), mtu);
-               goto error;
+               goto drop;
        }
 
        skb->dev = netdev_vport->dev;
@@ -312,19 +312,15 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
                        nskb = skb_gso_segment(skb, features);
                        if (!nskb) {
                                if (unlikely(skb_cloned(skb) &&
-                                   pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) {
-                                       kfree_skb(skb);
-                                       return 0;
-                               }
+                                   pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+                                       goto drop;
 
                                skb_shinfo(skb)->gso_type &= ~SKB_GSO_DODGY;
                                goto tag;
                        }
 
-                       if (IS_ERR(nskb)) {
-                               kfree_skb(skb);
-                               return 0;
-                       }
+                       if (IS_ERR(nskb))
+                               goto drop;
                        consume_skb(skb);
                        skb = nskb;
 
@@ -358,9 +354,8 @@ tag:
 
        return len;
 
-error:
+drop:
        kfree_skb(skb);
-       ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
        return 0;
 }
 
index 3558b0e..6a9ff26 100644 (file)
@@ -259,11 +259,8 @@ error:
 
 static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
 {
-       if (unlikely(!OVS_CB(skb)->tun_key)) {
-               ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
-               kfree_skb(skb);
-               return 0;
-       }
+       if (unlikely(!OVS_CB(skb)->tun_key))
+               return -EINVAL;
 
        return ovs_tnl_send(vport, skb, IPPROTO_UDP,
                        VXLAN_HLEN, vxlan_build_header);
index b63ed59..c2460c5 100644 (file)
@@ -438,7 +438,12 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
                stats->tx_packets++;
                stats->tx_bytes += sent;
                u64_stats_update_end(&stats->syncp);
-       }
+       } else if (sent < 0) {
+               ovs_vport_record_error(vport, VPORT_E_TX_ERROR);
+               kfree_skb(skb);
+       } else
+               ovs_vport_record_error(vport, VPORT_E_TX_DROPPED);
+
        return sent;
 }
 
index ab17a5f..8325ee1 100644 (file)
@@ -138,7 +138,8 @@ struct vport_parms {
  * existing vport to a &struct sk_buff.  May be %NULL for a vport that does not
  * have any configuration.
  * @get_name: Get the device's name.
- * @send: Send a packet on the device.  Returns the length of the packet sent.
+ * @send: Send a packet on the device.  Returns the length of the packet sent,
+ * zero for dropped packets or negative for error.
  */
 struct vport_ops {
        enum ovs_vport_type type;