mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
net: ipv4: ipmr: Split ipmr_queue_xmit() in two
Some of the work of ipmr_queue_xmit() is specific to IPMR forwarding, and should not take place on the output path. In order to allow reuse of the common parts, split the function into two: the ipmr_prepare_xmit() helper that takes care of the common bits, and the ipmr_queue_fwd_xmit(), which invokes the former and encapsulates the whole forwarding algorithm. Signed-off-by: Petr Machata <petrm@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org> Link: https://patch.msgid.link/4e8db165572a4f8bd29a723a801e854e9d20df4d.1750113335.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
3b7bc938e0
commit
b2e653bcff
|
|
@ -1853,8 +1853,8 @@ static bool ipmr_forward_offloaded(struct sk_buff *skb, struct mr_table *mrt,
|
|||
|
||||
/* Processing handlers for ipmr_forward, under rcu_read_lock() */
|
||||
|
||||
static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
|
||||
int in_vifi, struct sk_buff *skb, int vifi)
|
||||
static int ipmr_prepare_xmit(struct net *net, struct mr_table *mrt,
|
||||
struct sk_buff *skb, int vifi)
|
||||
{
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
struct vif_device *vif = &mrt->vif_table[vifi];
|
||||
|
|
@ -1865,7 +1865,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
|
|||
|
||||
vif_dev = vif_dev_read(vif);
|
||||
if (!vif_dev)
|
||||
goto out_free;
|
||||
return -1;
|
||||
|
||||
if (vif->flags & VIFF_REGISTER) {
|
||||
WRITE_ONCE(vif->pkt_out, vif->pkt_out + 1);
|
||||
|
|
@ -1873,12 +1873,9 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
|
|||
DEV_STATS_ADD(vif_dev, tx_bytes, skb->len);
|
||||
DEV_STATS_INC(vif_dev, tx_packets);
|
||||
ipmr_cache_report(mrt, skb, vifi, IGMPMSG_WHOLEPKT);
|
||||
goto out_free;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ipmr_forward_offloaded(skb, mrt, in_vifi, vifi))
|
||||
goto out_free;
|
||||
|
||||
if (vif->flags & VIFF_TUNNEL) {
|
||||
rt = ip_route_output_ports(net, &fl4, NULL,
|
||||
vif->remote, vif->local,
|
||||
|
|
@ -1886,7 +1883,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
|
|||
IPPROTO_IPIP,
|
||||
iph->tos & INET_DSCP_MASK, vif->link);
|
||||
if (IS_ERR(rt))
|
||||
goto out_free;
|
||||
return -1;
|
||||
encap = sizeof(struct iphdr);
|
||||
} else {
|
||||
rt = ip_route_output_ports(net, &fl4, NULL, iph->daddr, 0,
|
||||
|
|
@ -1894,7 +1891,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
|
|||
IPPROTO_IPIP,
|
||||
iph->tos & INET_DSCP_MASK, vif->link);
|
||||
if (IS_ERR(rt))
|
||||
goto out_free;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (skb->len+encap > dst_mtu(&rt->dst) && (ntohs(iph->frag_off) & IP_DF)) {
|
||||
|
|
@ -1904,14 +1901,14 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
|
|||
*/
|
||||
IP_INC_STATS(net, IPSTATS_MIB_FRAGFAILS);
|
||||
ip_rt_put(rt);
|
||||
goto out_free;
|
||||
return -1;
|
||||
}
|
||||
|
||||
encap += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
|
||||
|
||||
if (skb_cow(skb, encap)) {
|
||||
ip_rt_put(rt);
|
||||
goto out_free;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WRITE_ONCE(vif->pkt_out, vif->pkt_out + 1);
|
||||
|
|
@ -1931,6 +1928,22 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
|
|||
DEV_STATS_ADD(vif_dev, tx_bytes, skb->len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipmr_queue_fwd_xmit(struct net *net, struct mr_table *mrt,
|
||||
int in_vifi, struct sk_buff *skb, int vifi)
|
||||
{
|
||||
struct rtable *rt;
|
||||
|
||||
if (ipmr_forward_offloaded(skb, mrt, in_vifi, vifi))
|
||||
goto out_free;
|
||||
|
||||
if (ipmr_prepare_xmit(net, mrt, skb, vifi))
|
||||
goto out_free;
|
||||
|
||||
rt = skb_rtable(skb);
|
||||
|
||||
IPCB(skb)->flags |= IPSKB_FORWARDED;
|
||||
|
||||
/* RFC1584 teaches, that DVMRP/PIM router must deliver packets locally
|
||||
|
|
@ -2062,8 +2075,8 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
|
|||
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
|
||||
if (skb2)
|
||||
ipmr_queue_xmit(net, mrt, true_vifi,
|
||||
skb2, psend);
|
||||
ipmr_queue_fwd_xmit(net, mrt, true_vifi,
|
||||
skb2, psend);
|
||||
}
|
||||
psend = ct;
|
||||
}
|
||||
|
|
@ -2074,10 +2087,10 @@ static void ip_mr_forward(struct net *net, struct mr_table *mrt,
|
|||
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
|
||||
if (skb2)
|
||||
ipmr_queue_xmit(net, mrt, true_vifi, skb2,
|
||||
psend);
|
||||
ipmr_queue_fwd_xmit(net, mrt, true_vifi, skb2,
|
||||
psend);
|
||||
} else {
|
||||
ipmr_queue_xmit(net, mrt, true_vifi, skb, psend);
|
||||
ipmr_queue_fwd_xmit(net, mrt, true_vifi, skb, psend);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user