Commit 9972f134 authored by David Ahern's avatar David Ahern Committed by David S. Miller

net: frags: Add VRF device index to cache and lookup

Fragmentation cache uses information from the IP header to reassemble
packets. That information can be duplicated across VRFs -- same source
and destination addresses, protocol and id. Handle fragmentation with
VRFs by adding the VRF device index to entries in the cache and the
lookup arg.
Signed-off-by: default avatarDavid Ahern <dsa@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f7ba868b
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include <linux/inet.h> #include <linux/inet.h>
#include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/vrf.h>
/* NOTE. Logic of IP defragmentation is parallel to corresponding IPv6 /* NOTE. Logic of IP defragmentation is parallel to corresponding IPv6
* code now. If you change something here, _PLEASE_ update ipv6/reassembly.c * code now. If you change something here, _PLEASE_ update ipv6/reassembly.c
...@@ -77,6 +78,7 @@ struct ipq { ...@@ -77,6 +78,7 @@ struct ipq {
u8 ecn; /* RFC3168 support */ u8 ecn; /* RFC3168 support */
u16 max_df_size; /* largest frag with DF set seen */ u16 max_df_size; /* largest frag with DF set seen */
int iif; int iif;
int vif; /* VRF device index */
unsigned int rid; unsigned int rid;
struct inet_peer *peer; struct inet_peer *peer;
}; };
...@@ -99,6 +101,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, ...@@ -99,6 +101,7 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
struct ip4_create_arg { struct ip4_create_arg {
struct iphdr *iph; struct iphdr *iph;
u32 user; u32 user;
int vif;
}; };
static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot)
...@@ -127,7 +130,8 @@ static bool ip4_frag_match(const struct inet_frag_queue *q, const void *a) ...@@ -127,7 +130,8 @@ static bool ip4_frag_match(const struct inet_frag_queue *q, const void *a)
qp->saddr == arg->iph->saddr && qp->saddr == arg->iph->saddr &&
qp->daddr == arg->iph->daddr && qp->daddr == arg->iph->daddr &&
qp->protocol == arg->iph->protocol && qp->protocol == arg->iph->protocol &&
qp->user == arg->user; qp->user == arg->user &&
qp->vif == arg->vif;
} }
static void ip4_frag_init(struct inet_frag_queue *q, const void *a) static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
...@@ -144,6 +148,7 @@ static void ip4_frag_init(struct inet_frag_queue *q, const void *a) ...@@ -144,6 +148,7 @@ static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
qp->ecn = ip4_frag_ecn(arg->iph->tos); qp->ecn = ip4_frag_ecn(arg->iph->tos);
qp->saddr = arg->iph->saddr; qp->saddr = arg->iph->saddr;
qp->daddr = arg->iph->daddr; qp->daddr = arg->iph->daddr;
qp->vif = arg->vif;
qp->user = arg->user; qp->user = arg->user;
qp->peer = sysctl_ipfrag_max_dist ? qp->peer = sysctl_ipfrag_max_dist ?
inet_getpeer_v4(net->ipv4.peers, arg->iph->saddr, 1) : NULL; inet_getpeer_v4(net->ipv4.peers, arg->iph->saddr, 1) : NULL;
...@@ -244,7 +249,8 @@ static void ip_expire(unsigned long arg) ...@@ -244,7 +249,8 @@ static void ip_expire(unsigned long arg)
/* Find the correct entry in the "incomplete datagrams" queue for /* Find the correct entry in the "incomplete datagrams" queue for
* this IP datagram, and create new one, if nothing is found. * this IP datagram, and create new one, if nothing is found.
*/ */
static struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user) static struct ipq *ip_find(struct net *net, struct iphdr *iph,
u32 user, int vif)
{ {
struct inet_frag_queue *q; struct inet_frag_queue *q;
struct ip4_create_arg arg; struct ip4_create_arg arg;
...@@ -252,6 +258,7 @@ static struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user) ...@@ -252,6 +258,7 @@ static struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
arg.iph = iph; arg.iph = iph;
arg.user = user; arg.user = user;
arg.vif = vif;
hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
...@@ -648,14 +655,15 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, ...@@ -648,14 +655,15 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
/* Process an incoming IP datagram fragment. */ /* Process an incoming IP datagram fragment. */
int ip_defrag(struct sk_buff *skb, u32 user) int ip_defrag(struct sk_buff *skb, u32 user)
{ {
struct net_device *dev = skb->dev ? : skb_dst(skb)->dev;
int vif = vrf_master_ifindex_rcu(dev);
struct net *net = dev_net(dev);
struct ipq *qp; struct ipq *qp;
struct net *net;
net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev);
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
/* Lookup (or create) queue header */ /* Lookup (or create) queue header */
qp = ip_find(net, ip_hdr(skb), user); qp = ip_find(net, ip_hdr(skb), user, vif);
if (qp) { if (qp) {
int ret; int ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment