Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95603e22 authored by Michel Machado's avatar Michel Machado Committed by David S. Miller
Browse files

net-next: add dev_loopback_xmit() to avoid duplicate code



Add dev_loopback_xmit() in order to deduplicate functions
ip_dev_loopback_xmit() (in net/ipv4/ip_output.c) and
ip6_dev_loopback_xmit() (in net/ipv6/ip6_output.c).

I was about to reinvent the wheel when I noticed that
ip_dev_loopback_xmit() and ip6_dev_loopback_xmit() do exactly what I
need and are not IP-only functions, but they were not available to reuse
elsewhere.

ip6_dev_loopback_xmit() does not have line "skb_dst_force(skb);", but I
understand that this is harmless, and should be in dev_loopback_xmit().

Signed-off-by: default avatarMichel Machado <michel@digirati.com.br>
CC: "David S. Miller" <davem@davemloft.net>
CC: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
CC: James Morris <jmorris@namei.org>
CC: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
CC: Patrick McHardy <kaber@trash.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Jiri Pirko <jpirko@redhat.com>
CC: "Michał Mirosław" <mirq-linux@rere.qmqm.pl>
CC: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent de063b70
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -1627,6 +1627,7 @@ extern int dev_alloc_name(struct net_device *dev, const char *name);
extern int		dev_open(struct net_device *dev);
extern int		dev_open(struct net_device *dev);
extern int		dev_close(struct net_device *dev);
extern int		dev_close(struct net_device *dev);
extern void		dev_disable_lro(struct net_device *dev);
extern void		dev_disable_lro(struct net_device *dev);
extern int		dev_loopback_xmit(struct sk_buff *newskb);
extern int		dev_queue_xmit(struct sk_buff *skb);
extern int		dev_queue_xmit(struct sk_buff *skb);
extern int		register_netdevice(struct net_device *dev);
extern int		register_netdevice(struct net_device *dev);
extern void		unregister_netdevice_queue(struct net_device *dev,
extern void		unregister_netdevice_queue(struct net_device *dev,
+17 −0
Original line number Original line Diff line number Diff line
@@ -2475,6 +2475,23 @@ static void skb_update_prio(struct sk_buff *skb)
static DEFINE_PER_CPU(int, xmit_recursion);
static DEFINE_PER_CPU(int, xmit_recursion);
#define RECURSION_LIMIT 10
#define RECURSION_LIMIT 10


/**
 *	dev_loopback_xmit - loop back @skb
 *	@skb: buffer to transmit
 */
int dev_loopback_xmit(struct sk_buff *skb)
{
	skb_reset_mac_header(skb);
	__skb_pull(skb, skb_network_offset(skb));
	skb->pkt_type = PACKET_LOOPBACK;
	skb->ip_summed = CHECKSUM_UNNECESSARY;
	WARN_ON(!skb_dst(skb));
	skb_dst_force(skb);
	netif_rx_ni(skb);
	return 0;
}
EXPORT_SYMBOL(dev_loopback_xmit);

/**
/**
 *	dev_queue_xmit - transmit a buffer
 *	dev_queue_xmit - transmit a buffer
 *	@skb: buffer to transmit
 *	@skb: buffer to transmit
+2 −15
Original line number Original line Diff line number Diff line
@@ -113,19 +113,6 @@ int ip_local_out(struct sk_buff *skb)
}
}
EXPORT_SYMBOL_GPL(ip_local_out);
EXPORT_SYMBOL_GPL(ip_local_out);


/* dev_loopback_xmit for use with netfilter. */
static int ip_dev_loopback_xmit(struct sk_buff *newskb)
{
	skb_reset_mac_header(newskb);
	__skb_pull(newskb, skb_network_offset(newskb));
	newskb->pkt_type = PACKET_LOOPBACK;
	newskb->ip_summed = CHECKSUM_UNNECESSARY;
	WARN_ON(!skb_dst(newskb));
	skb_dst_force(newskb);
	netif_rx_ni(newskb);
	return 0;
}

static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst)
static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst)
{
{
	int ttl = inet->uc_ttl;
	int ttl = inet->uc_ttl;
@@ -281,7 +268,7 @@ int ip_mc_output(struct sk_buff *skb)
			if (newskb)
			if (newskb)
				NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,
				NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING,
					newskb, NULL, newskb->dev,
					newskb, NULL, newskb->dev,
					ip_dev_loopback_xmit);
					dev_loopback_xmit);
		}
		}


		/* Multicasts with ttl 0 must not go beyond the host */
		/* Multicasts with ttl 0 must not go beyond the host */
@@ -296,7 +283,7 @@ int ip_mc_output(struct sk_buff *skb)
		struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
		struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
		if (newskb)
		if (newskb)
			NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, newskb,
			NF_HOOK(NFPROTO_IPV4, NF_INET_POST_ROUTING, newskb,
				NULL, newskb->dev, ip_dev_loopback_xmit);
				NULL, newskb->dev, dev_loopback_xmit);
	}
	}


	return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL,
	return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL,
+1 −14
Original line number Original line Diff line number Diff line
@@ -83,19 +83,6 @@ int ip6_local_out(struct sk_buff *skb)
}
}
EXPORT_SYMBOL_GPL(ip6_local_out);
EXPORT_SYMBOL_GPL(ip6_local_out);


/* dev_loopback_xmit for use with netfilter. */
static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
{
	skb_reset_mac_header(newskb);
	__skb_pull(newskb, skb_network_offset(newskb));
	newskb->pkt_type = PACKET_LOOPBACK;
	newskb->ip_summed = CHECKSUM_UNNECESSARY;
	WARN_ON(!skb_dst(newskb));

	netif_rx_ni(newskb);
	return 0;
}

static int ip6_finish_output2(struct sk_buff *skb)
static int ip6_finish_output2(struct sk_buff *skb)
{
{
	struct dst_entry *dst = skb_dst(skb);
	struct dst_entry *dst = skb_dst(skb);
@@ -121,7 +108,7 @@ static int ip6_finish_output2(struct sk_buff *skb)
			if (newskb)
			if (newskb)
				NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING,
				NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING,
					newskb, NULL, newskb->dev,
					newskb, NULL, newskb->dev,
					ip6_dev_loopback_xmit);
					dev_loopback_xmit);


			if (ipv6_hdr(skb)->hop_limit == 0) {
			if (ipv6_hdr(skb)->hop_limit == 0) {
				IP6_INC_STATS(dev_net(dev), idev,
				IP6_INC_STATS(dev_net(dev), idev,