提交 039f5062 编写于 作者: P Pravin B Shelar 提交者: David S. Miller

ip_tunnel: Move stats update to iptunnel_xmit()

By moving stats update into iptunnel_xmit(), we can simplify
iptunnel_xmit() usage. With this change there is no need to
call another function (iptunnel_xmit_stats()) to update stats
in tunnel xmit code path.
Signed-off-by: NPravin B Shelar <pshelar@nicira.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 d7d3e25f
...@@ -918,12 +918,11 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -918,12 +918,11 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
df = 0; df = 0;
} }
err = udp_tunnel_xmit_skb(rt, gs4->sock->sk, skb, fl4.saddr, fl4.daddr, udp_tunnel_xmit_skb(rt, gs4->sock->sk, skb, fl4.saddr, fl4.daddr,
tos, ttl, df, sport, geneve->dst_port, tos, ttl, df, sport, geneve->dst_port,
!net_eq(geneve->net, dev_net(geneve->dev)), !net_eq(geneve->net, dev_net(geneve->dev)),
!(flags & GENEVE_F_UDP_CSUM)); !(flags & GENEVE_F_UDP_CSUM));
iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_error: tx_error:
...@@ -1005,10 +1004,10 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -1005,10 +1004,10 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
ttl = 1; ttl = 1;
ttl = ttl ? : ip6_dst_hoplimit(dst); ttl = ttl ? : ip6_dst_hoplimit(dst);
} }
err = udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev, udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev,
&fl6.saddr, &fl6.daddr, prio, ttl, &fl6.saddr, &fl6.daddr, prio, ttl,
sport, geneve->dst_port, sport, geneve->dst_port,
!!(flags & GENEVE_F_UDP_ZERO_CSUM6_TX)); !!(flags & GENEVE_F_UDP_ZERO_CSUM6_TX));
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_error: tx_error:
......
...@@ -1841,9 +1841,10 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk ...@@ -1841,9 +1841,10 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk
skb_set_inner_protocol(skb, htons(ETH_P_TEB)); skb_set_inner_protocol(skb, htons(ETH_P_TEB));
return udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos, udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos, ttl, df,
ttl, df, src_port, dst_port, xnet, src_port, dst_port, xnet,
!(vxflags & VXLAN_F_UDP_CSUM)); !(vxflags & VXLAN_F_UDP_CSUM));
return 0;
} }
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
...@@ -2056,8 +2057,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -2056,8 +2057,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
skb = NULL; skb = NULL;
goto rt_tx_error; goto rt_tx_error;
} }
iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
} else { } else {
struct dst_entry *ndst; struct dst_entry *ndst;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/if_tunnel.h> #include <linux/if_tunnel.h>
#include <linux/ip6_tunnel.h> #include <linux/ip6_tunnel.h>
#include <net/ip_tunnels.h>
#define IP6TUNNEL_ERR_TIMEO (30*HZ) #define IP6TUNNEL_ERR_TIMEO (30*HZ)
...@@ -83,22 +84,12 @@ int ip6_tnl_get_iflink(const struct net_device *dev); ...@@ -83,22 +84,12 @@ int ip6_tnl_get_iflink(const struct net_device *dev);
static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
{ {
struct net_device_stats *stats = &dev->stats;
int pkt_len, err; int pkt_len, err;
pkt_len = skb->len - skb_inner_network_offset(skb); pkt_len = skb->len - skb_inner_network_offset(skb);
err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb); err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb);
if (unlikely(net_xmit_eval(err)))
if (net_xmit_eval(err) == 0) { pkt_len = -1;
struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats); iptunnel_xmit_stats(dev, pkt_len);
u64_stats_update_begin(&tstats->syncp);
tstats->tx_bytes += pkt_len;
tstats->tx_packets++;
u64_stats_update_end(&tstats->syncp);
put_cpu_ptr(tstats);
} else {
stats->tx_errors++;
stats->tx_aborted_errors++;
}
} }
#endif #endif
...@@ -273,32 +273,34 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph, ...@@ -273,32 +273,34 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,
} }
int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto); int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, u8 proto, __be32 src, __be32 dst, u8 proto,
u8 tos, u8 ttl, __be16 df, bool xnet); u8 tos, u8 ttl, __be16 df, bool xnet);
struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md, struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
gfp_t flags); gfp_t flags);
struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum, struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum,
int gso_type_mask); int gso_type_mask);
static inline void iptunnel_xmit_stats(int err, static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len)
struct net_device_stats *err_stats,
struct pcpu_sw_netstats __percpu *stats)
{ {
if (err > 0) { if (pkt_len > 0) {
struct pcpu_sw_netstats *tstats = get_cpu_ptr(stats); struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats);
u64_stats_update_begin(&tstats->syncp); u64_stats_update_begin(&tstats->syncp);
tstats->tx_bytes += err; tstats->tx_bytes += pkt_len;
tstats->tx_packets++; tstats->tx_packets++;
u64_stats_update_end(&tstats->syncp); u64_stats_update_end(&tstats->syncp);
put_cpu_ptr(tstats); put_cpu_ptr(tstats);
} else if (err < 0) {
err_stats->tx_errors++;
err_stats->tx_aborted_errors++;
} else { } else {
err_stats->tx_dropped++; struct net_device_stats *err_stats = &dev->stats;
if (pkt_len < 0) {
err_stats->tx_errors++;
err_stats->tx_aborted_errors++;
} else {
err_stats->tx_dropped++;
}
} }
} }
......
...@@ -78,10 +78,10 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, ...@@ -78,10 +78,10 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
struct udp_tunnel_sock_cfg *sock_cfg); struct udp_tunnel_sock_cfg *sock_cfg);
/* Transmit the skb using UDP encapsulation. */ /* Transmit the skb using UDP encapsulation. */
int udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl, __be32 src, __be32 dst, __u8 tos, __u8 ttl,
__be16 df, __be16 src_port, __be16 dst_port, __be16 df, __be16 src_port, __be16 dst_port,
bool xnet, bool nocheck); bool xnet, bool nocheck);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk, int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
......
...@@ -561,10 +561,9 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -561,10 +561,9 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)
tunnel_id_to_key(tun_info->key.tun_id), 0); tunnel_id_to_key(tun_info->key.tun_id), 0);
df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
err = iptunnel_xmit(skb->sk, rt, skb, fl.saddr,
key->u.ipv4.dst, IPPROTO_GRE, iptunnel_xmit(skb->sk, rt, skb, fl.saddr, key->u.ipv4.dst, IPPROTO_GRE,
key->tos, key->ttl, df, false); key->tos, key->ttl, df, false);
iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
return; return;
err_free_rt: err_free_rt:
......
...@@ -656,7 +656,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, ...@@ -656,7 +656,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
struct rtable *rt; /* Route to the other host */ struct rtable *rt; /* Route to the other host */
unsigned int max_headroom; /* The extra header space needed */ unsigned int max_headroom; /* The extra header space needed */
__be32 dst; __be32 dst;
int err;
bool connected; bool connected;
inner_iph = (const struct iphdr *)skb_inner_network_header(skb); inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
...@@ -794,10 +793,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, ...@@ -794,10 +793,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
return; return;
} }
err = iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl,
tos, ttl, df, !net_eq(tunnel->net, dev_net(dev))); df, !net_eq(tunnel->net, dev_net(dev)));
iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
return; return;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
......
...@@ -47,12 +47,13 @@ ...@@ -47,12 +47,13 @@
#include <net/rtnetlink.h> #include <net/rtnetlink.h>
#include <net/dst_metadata.h> #include <net/dst_metadata.h>
int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 proto, __be32 src, __be32 dst, __u8 proto,
__u8 tos, __u8 ttl, __be16 df, bool xnet) __u8 tos, __u8 ttl, __be16 df, bool xnet)
{ {
int pkt_len = skb->len - skb_inner_network_offset(skb); int pkt_len = skb->len - skb_inner_network_offset(skb);
struct net *net = dev_net(rt->dst.dev); struct net *net = dev_net(rt->dst.dev);
struct net_device *dev = skb->dev;
struct iphdr *iph; struct iphdr *iph;
int err; int err;
...@@ -81,7 +82,7 @@ int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, ...@@ -81,7 +82,7 @@ int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
err = ip_local_out(net, sk, skb); err = ip_local_out(net, sk, skb);
if (unlikely(net_xmit_eval(err))) if (unlikely(net_xmit_eval(err)))
pkt_len = 0; pkt_len = 0;
return pkt_len; iptunnel_xmit_stats(dev, pkt_len);
} }
EXPORT_SYMBOL_GPL(iptunnel_xmit); EXPORT_SYMBOL_GPL(iptunnel_xmit);
......
...@@ -199,7 +199,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, ...@@ -199,7 +199,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
err = dst_output(tunnel->net, skb->sk, skb); err = dst_output(tunnel->net, skb->sk, skb);
if (net_xmit_eval(err) == 0) if (net_xmit_eval(err) == 0)
err = skb->len; err = skb->len;
iptunnel_xmit_stats(err, &dev->stats, dev->tstats); iptunnel_xmit_stats(dev, err);
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_error_icmp: tx_error_icmp:
......
...@@ -74,10 +74,10 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock, ...@@ -74,10 +74,10 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
} }
EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock); EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
int udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl, __be32 src, __be32 dst, __u8 tos, __u8 ttl,
__be16 df, __be16 src_port, __be16 dst_port, __be16 df, __be16 src_port, __be16 dst_port,
bool xnet, bool nocheck) bool xnet, bool nocheck)
{ {
struct udphdr *uh; struct udphdr *uh;
...@@ -91,8 +91,7 @@ int udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, ...@@ -91,8 +91,7 @@ int udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
udp_set_csum(nocheck, skb, src, dst, skb->len); udp_set_csum(nocheck, skb, src, dst, skb->len);
return iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, iptunnel_xmit(sk, rt, skb, src, dst, IPPROTO_UDP, tos, ttl, df, xnet);
tos, ttl, df, xnet);
} }
EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb); EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb);
......
...@@ -820,7 +820,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, ...@@ -820,7 +820,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
const struct in6_addr *addr6; const struct in6_addr *addr6;
int addr_type; int addr_type;
u8 ttl; u8 ttl;
int err;
u8 protocol = IPPROTO_IPV6; u8 protocol = IPPROTO_IPV6;
int t_hlen = tunnel->hlen + sizeof(struct iphdr); int t_hlen = tunnel->hlen + sizeof(struct iphdr);
...@@ -983,10 +982,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, ...@@ -983,10 +982,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
skb_set_inner_ipproto(skb, IPPROTO_IPV6); skb_set_inner_ipproto(skb, IPPROTO_IPV6);
err = iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl,
protocol, tos, ttl, df, df, !net_eq(tunnel->net, dev_net(dev)));
!net_eq(tunnel->net, dev_net(dev)));
iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_error_icmp: tx_error_icmp:
......
...@@ -182,15 +182,9 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, ...@@ -182,15 +182,9 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb,
goto tx_error; goto tx_error;
} }
ttl = ip4_dst_hoplimit(&rt->dst); ttl = ip4_dst_hoplimit(&rt->dst);
err = udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr,
src->ipv4.s_addr, dst->ipv4.s_addr, 0, ttl, 0, src->udp_port,
dst->ipv4.s_addr, 0, ttl, 0, dst->udp_port, false, true);
src->udp_port, dst->udp_port,
false, true);
if (err < 0) {
ip_rt_put(rt);
goto tx_error;
}
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
} else { } else {
struct dst_entry *ndst; struct dst_entry *ndst;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册