xfrm: add is_ipip to struct xfrm_input_afinfo
This patch is to add a new member is_ipip to struct xfrm_input_afinfo, to allow another group family of callback functions to be registered with is_ipip set. This will be used for doing a callback for struct xfrm(6)_tunnel of ipip/ipv6 tunnels in xfrm_input() by calling xfrm_rcv_cb(), which is needed by ipip/ipv6 tunnels' support in ip(6)_vti and xfrm interface in the next patches. Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
This commit is contained in:

committed by
Steffen Klassert

parent
428d2459cc
commit
1475ee0ac9
@@ -373,7 +373,8 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
|
|||||||
struct xfrm_state_afinfo *xfrm_state_afinfo_get_rcu(unsigned int family);
|
struct xfrm_state_afinfo *xfrm_state_afinfo_get_rcu(unsigned int family);
|
||||||
|
|
||||||
struct xfrm_input_afinfo {
|
struct xfrm_input_afinfo {
|
||||||
unsigned int family;
|
u8 family;
|
||||||
|
bool is_ipip;
|
||||||
int (*callback)(struct sk_buff *skb, u8 protocol,
|
int (*callback)(struct sk_buff *skb, u8 protocol,
|
||||||
int err);
|
int err);
|
||||||
};
|
};
|
||||||
|
@@ -42,7 +42,7 @@ struct xfrm_trans_cb {
|
|||||||
#define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0]))
|
#define XFRM_TRANS_SKB_CB(__skb) ((struct xfrm_trans_cb *)&((__skb)->cb[0]))
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(xfrm_input_afinfo_lock);
|
static DEFINE_SPINLOCK(xfrm_input_afinfo_lock);
|
||||||
static struct xfrm_input_afinfo const __rcu *xfrm_input_afinfo[AF_INET6 + 1];
|
static struct xfrm_input_afinfo const __rcu *xfrm_input_afinfo[2][AF_INET6 + 1];
|
||||||
|
|
||||||
static struct gro_cells gro_cells;
|
static struct gro_cells gro_cells;
|
||||||
static struct net_device xfrm_napi_dev;
|
static struct net_device xfrm_napi_dev;
|
||||||
@@ -53,14 +53,14 @@ int xfrm_input_register_afinfo(const struct xfrm_input_afinfo *afinfo)
|
|||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (WARN_ON(afinfo->family >= ARRAY_SIZE(xfrm_input_afinfo)))
|
if (WARN_ON(afinfo->family > AF_INET6))
|
||||||
return -EAFNOSUPPORT;
|
return -EAFNOSUPPORT;
|
||||||
|
|
||||||
spin_lock_bh(&xfrm_input_afinfo_lock);
|
spin_lock_bh(&xfrm_input_afinfo_lock);
|
||||||
if (unlikely(xfrm_input_afinfo[afinfo->family] != NULL))
|
if (unlikely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family]))
|
||||||
err = -EEXIST;
|
err = -EEXIST;
|
||||||
else
|
else
|
||||||
rcu_assign_pointer(xfrm_input_afinfo[afinfo->family], afinfo);
|
rcu_assign_pointer(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family], afinfo);
|
||||||
spin_unlock_bh(&xfrm_input_afinfo_lock);
|
spin_unlock_bh(&xfrm_input_afinfo_lock);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -71,11 +71,11 @@ int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
spin_lock_bh(&xfrm_input_afinfo_lock);
|
spin_lock_bh(&xfrm_input_afinfo_lock);
|
||||||
if (likely(xfrm_input_afinfo[afinfo->family] != NULL)) {
|
if (likely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family])) {
|
||||||
if (unlikely(xfrm_input_afinfo[afinfo->family] != afinfo))
|
if (unlikely(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family] != afinfo))
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
else
|
else
|
||||||
RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->family], NULL);
|
RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->is_ipip][afinfo->family], NULL);
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&xfrm_input_afinfo_lock);
|
spin_unlock_bh(&xfrm_input_afinfo_lock);
|
||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
@@ -83,15 +83,15 @@ int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(xfrm_input_unregister_afinfo);
|
EXPORT_SYMBOL(xfrm_input_unregister_afinfo);
|
||||||
|
|
||||||
static const struct xfrm_input_afinfo *xfrm_input_get_afinfo(unsigned int family)
|
static const struct xfrm_input_afinfo *xfrm_input_get_afinfo(u8 family, bool is_ipip)
|
||||||
{
|
{
|
||||||
const struct xfrm_input_afinfo *afinfo;
|
const struct xfrm_input_afinfo *afinfo;
|
||||||
|
|
||||||
if (WARN_ON_ONCE(family >= ARRAY_SIZE(xfrm_input_afinfo)))
|
if (WARN_ON_ONCE(family > AF_INET6))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
afinfo = rcu_dereference(xfrm_input_afinfo[family]);
|
afinfo = rcu_dereference(xfrm_input_afinfo[is_ipip][family]);
|
||||||
if (unlikely(!afinfo))
|
if (unlikely(!afinfo))
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return afinfo;
|
return afinfo;
|
||||||
@@ -100,9 +100,11 @@ static const struct xfrm_input_afinfo *xfrm_input_get_afinfo(unsigned int family
|
|||||||
static int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family, u8 protocol,
|
static int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family, u8 protocol,
|
||||||
int err)
|
int err)
|
||||||
{
|
{
|
||||||
|
bool is_ipip = (protocol == IPPROTO_IPIP || protocol == IPPROTO_IPV6);
|
||||||
|
const struct xfrm_input_afinfo *afinfo;
|
||||||
int ret;
|
int ret;
|
||||||
const struct xfrm_input_afinfo *afinfo = xfrm_input_get_afinfo(family);
|
|
||||||
|
|
||||||
|
afinfo = xfrm_input_get_afinfo(family, is_ipip);
|
||||||
if (!afinfo)
|
if (!afinfo)
|
||||||
return -EAFNOSUPPORT;
|
return -EAFNOSUPPORT;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user