From be7cd27e44258bdb3c4e7dd8fd7389b5db56d55a Mon Sep 17 00:00:00 2001 From: Pravin B Shelar Date: Mon, 6 May 2013 10:31:01 -0700 Subject: [PATCH] datapath: Unify vport error stats handling. Following patch changes vport->send return type so that vport layer can do error accounting. Signed-off-by: Pravin B Shelar Acked-by: Jesse Gross --- datapath/tunnel.c | 33 ++++++++++++++------------------- datapath/vport-gre.c | 14 ++++---------- datapath/vport-lisp.c | 13 +++---------- datapath/vport-netdev.c | 17 ++++++----------- datapath/vport-vxlan.c | 7 ++----- datapath/vport.c | 7 ++++++- datapath/vport.h | 3 ++- 7 files changed, 37 insertions(+), 57 deletions(-) diff --git a/datapath/tunnel.c b/datapath/tunnel.c index 0cc06073a..8cf1c167d 100644 --- a/datapath/tunnel.c +++ b/datapath/tunnel.c @@ -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; } diff --git a/datapath/vport-gre.c b/datapath/vport-gre.c index 0c7ae57cd..53c6b29d1 100644 --- a/datapath/vport-gre.c +++ b/datapath/vport-gre.c @@ -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); diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c index d45a4cc2d..554495d54 100644 --- a/datapath/vport-lisp.c +++ b/datapath/vport-lisp.c @@ -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) diff --git a/datapath/vport-netdev.c b/datapath/vport-netdev.c index 455807906..55592f988 100644 --- a/datapath/vport-netdev.c +++ b/datapath/vport-netdev.c @@ -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; } diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c index 3558b0e32..6a9ff2669 100644 --- a/datapath/vport-vxlan.c +++ b/datapath/vport-vxlan.c @@ -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); diff --git a/datapath/vport.c b/datapath/vport.c index b63ed5991..c2460c508 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -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; } diff --git a/datapath/vport.h b/datapath/vport.h index ab17a5fb3..8325ee1a7 100644 --- a/datapath/vport.h +++ b/datapath/vport.h @@ -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; -- 2.43.0