net: ipmr: remove some pimsm ifdefs and simplify

Add the helper pimsm_enabled() which replaces the old CONFIG_IP_PIMSM
define and is used to check if any version of PIM-SM has been enabled.
Use a single if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
for the pim-sm shared code. This is okay w.r.t IGMPMSG_WHOLEPKT because
only a VIFF_REGISTER device can send such packet, and it can't be
created if pimsm_enabled() is false.

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Nikolay Aleksandrov 2015-11-21 15:57:26 +01:00 committed by David S. Miller
parent f3d431810e
commit c316c629f1

View file

@ -67,10 +67,6 @@
#include <net/fib_rules.h> #include <net/fib_rules.h>
#include <linux/netconf.h> #include <linux/netconf.h>
#if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
#define CONFIG_IP_PIMSM 1
#endif
struct mr_table { struct mr_table {
struct list_head list; struct list_head list;
possible_net_t net; possible_net_t net;
@ -95,6 +91,11 @@ struct ipmr_result {
struct mr_table *mrt; struct mr_table *mrt;
}; };
static inline bool pimsm_enabled(void)
{
return IS_BUILTIN(CONFIG_IP_PIMSM_V1) || IS_BUILTIN(CONFIG_IP_PIMSM_V2);
}
/* Big lock, protecting vif table, mrt cache and mroute socket state. /* Big lock, protecting vif table, mrt cache and mroute socket state.
* Note that the changes are semaphored via rtnl_lock. * Note that the changes are semaphored via rtnl_lock.
*/ */
@ -454,8 +455,7 @@ failure:
return NULL; return NULL;
} }
#ifdef CONFIG_IP_PIMSM #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct net *net = dev_net(dev); struct net *net = dev_net(dev);
@ -552,6 +552,51 @@ failure:
unregister_netdevice(dev); unregister_netdevice(dev);
return NULL; return NULL;
} }
/* called with rcu_read_lock() */
static int __pim_rcv(struct mr_table *mrt, struct sk_buff *skb,
unsigned int pimlen)
{
struct net_device *reg_dev = NULL;
struct iphdr *encap;
encap = (struct iphdr *)(skb_transport_header(skb) + pimlen);
/*
* Check that:
* a. packet is really sent to a multicast group
* b. packet is not a NULL-REGISTER
* c. packet is not truncated
*/
if (!ipv4_is_multicast(encap->daddr) ||
encap->tot_len == 0 ||
ntohs(encap->tot_len) + pimlen > skb->len)
return 1;
read_lock(&mrt_lock);
if (mrt->mroute_reg_vif_num >= 0)
reg_dev = mrt->vif_table[mrt->mroute_reg_vif_num].dev;
read_unlock(&mrt_lock);
if (!reg_dev)
return 1;
skb->mac_header = skb->network_header;
skb_pull(skb, (u8 *)encap - skb->data);
skb_reset_network_header(skb);
skb->protocol = htons(ETH_P_IP);
skb->ip_summed = CHECKSUM_NONE;
skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
netif_rx(skb);
return NET_RX_SUCCESS;
}
#else
static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt)
{
return NULL;
}
#endif #endif
/** /**
@ -734,10 +779,10 @@ static int vif_add(struct net *net, struct mr_table *mrt,
return -EADDRINUSE; return -EADDRINUSE;
switch (vifc->vifc_flags) { switch (vifc->vifc_flags) {
#ifdef CONFIG_IP_PIMSM
case VIFF_REGISTER: case VIFF_REGISTER:
/* if (!pimsm_enabled())
* Special Purpose VIF in PIM return -EINVAL;
/* Special Purpose VIF in PIM
* All the packets will be sent to the daemon * All the packets will be sent to the daemon
*/ */
if (mrt->mroute_reg_vif_num >= 0) if (mrt->mroute_reg_vif_num >= 0)
@ -752,7 +797,6 @@ static int vif_add(struct net *net, struct mr_table *mrt,
return err; return err;
} }
break; break;
#endif
case VIFF_TUNNEL: case VIFF_TUNNEL:
dev = ipmr_new_tunnel(net, vifc); dev = ipmr_new_tunnel(net, vifc);
if (!dev) if (!dev)
@ -942,34 +986,29 @@ static void ipmr_cache_resolve(struct net *net, struct mr_table *mrt,
} }
} }
/* /* Bounce a cache query up to mrouted. We could use netlink for this but mrouted
* Bounce a cache query up to mrouted. We could use netlink for this but mrouted * expects the following bizarre scheme.
* expects the following bizarre scheme.
* *
* Called under mrt_lock. * Called under mrt_lock.
*/ */
static int ipmr_cache_report(struct mr_table *mrt, static int ipmr_cache_report(struct mr_table *mrt,
struct sk_buff *pkt, vifi_t vifi, int assert) struct sk_buff *pkt, vifi_t vifi, int assert)
{ {
struct sk_buff *skb;
const int ihl = ip_hdrlen(pkt); const int ihl = ip_hdrlen(pkt);
struct sock *mroute_sk;
struct igmphdr *igmp; struct igmphdr *igmp;
struct igmpmsg *msg; struct igmpmsg *msg;
struct sock *mroute_sk; struct sk_buff *skb;
int ret; int ret;
#ifdef CONFIG_IP_PIMSM
if (assert == IGMPMSG_WHOLEPKT) if (assert == IGMPMSG_WHOLEPKT)
skb = skb_realloc_headroom(pkt, sizeof(struct iphdr)); skb = skb_realloc_headroom(pkt, sizeof(struct iphdr));
else else
#endif
skb = alloc_skb(128, GFP_ATOMIC); skb = alloc_skb(128, GFP_ATOMIC);
if (!skb) if (!skb)
return -ENOBUFS; return -ENOBUFS;
#ifdef CONFIG_IP_PIMSM
if (assert == IGMPMSG_WHOLEPKT) { if (assert == IGMPMSG_WHOLEPKT) {
/* Ugly, but we have no choice with this interface. /* Ugly, but we have no choice with this interface.
* Duplicate old header, fix ihl, length etc. * Duplicate old header, fix ihl, length etc.
@ -987,28 +1026,23 @@ static int ipmr_cache_report(struct mr_table *mrt,
ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2; ip_hdr(skb)->ihl = sizeof(struct iphdr) >> 2;
ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) + ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(pkt)->tot_len) +
sizeof(struct iphdr)); sizeof(struct iphdr));
} else } else {
#endif /* Copy the IP header */
{ skb_set_network_header(skb, skb->len);
skb_put(skb, ihl);
/* Copy the IP header */ skb_copy_to_linear_data(skb, pkt->data, ihl);
/* Flag to the kernel this is a route add */
skb_set_network_header(skb, skb->len); ip_hdr(skb)->protocol = 0;
skb_put(skb, ihl); msg = (struct igmpmsg *)skb_network_header(skb);
skb_copy_to_linear_data(skb, pkt->data, ihl); msg->im_vif = vifi;
ip_hdr(skb)->protocol = 0; /* Flag to the kernel this is a route add */ skb_dst_set(skb, dst_clone(skb_dst(pkt)));
msg = (struct igmpmsg *)skb_network_header(skb); /* Add our header */
msg->im_vif = vifi; igmp = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr));
skb_dst_set(skb, dst_clone(skb_dst(pkt))); igmp->type = assert;
msg->im_msgtype = assert;
/* Add our header */ igmp->code = 0;
ip_hdr(skb)->tot_len = htons(skb->len); /* Fix the length */
igmp = (struct igmphdr *)skb_put(skb, sizeof(struct igmphdr)); skb->transport_header = skb->network_header;
igmp->type =
msg->im_msgtype = assert;
igmp->code = 0;
ip_hdr(skb)->tot_len = htons(skb->len); /* Fix the length */
skb->transport_header = skb->network_header;
} }
rcu_read_lock(); rcu_read_lock();
@ -1020,7 +1054,6 @@ static int ipmr_cache_report(struct mr_table *mrt,
} }
/* Deliver to mrouted */ /* Deliver to mrouted */
ret = sock_queue_rcv_skb(mroute_sk, skb); ret = sock_queue_rcv_skb(mroute_sk, skb);
rcu_read_unlock(); rcu_read_unlock();
if (ret < 0) { if (ret < 0) {
@ -1377,11 +1410,12 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
mrt->mroute_do_assert = v; mrt->mroute_do_assert = v;
return 0; return 0;
} }
#ifdef CONFIG_IP_PIMSM
case MRT_PIM: case MRT_PIM:
{ {
int v; int v;
if (!pimsm_enabled())
return -ENOPROTOOPT;
if (optlen != sizeof(v)) if (optlen != sizeof(v))
return -EINVAL; return -EINVAL;
if (get_user(v, (int __user *)optval)) if (get_user(v, (int __user *)optval))
@ -1397,7 +1431,6 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
rtnl_unlock(); rtnl_unlock();
return ret; return ret;
} }
#endif
#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
case MRT_TABLE: case MRT_TABLE:
{ {
@ -1452,9 +1485,7 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int
return -ENOENT; return -ENOENT;
if (optname != MRT_VERSION && if (optname != MRT_VERSION &&
#ifdef CONFIG_IP_PIMSM
optname != MRT_PIM && optname != MRT_PIM &&
#endif
optname != MRT_ASSERT) optname != MRT_ASSERT)
return -ENOPROTOOPT; return -ENOPROTOOPT;
@ -1467,14 +1498,15 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int
if (put_user(olr, optlen)) if (put_user(olr, optlen))
return -EFAULT; return -EFAULT;
if (optname == MRT_VERSION) if (optname == MRT_VERSION) {
val = 0x0305; val = 0x0305;
#ifdef CONFIG_IP_PIMSM } else if (optname == MRT_PIM) {
else if (optname == MRT_PIM) if (!pimsm_enabled())
return -ENOPROTOOPT;
val = mrt->mroute_do_pim; val = mrt->mroute_do_pim;
#endif } else {
else
val = mrt->mroute_do_assert; val = mrt->mroute_do_assert;
}
if (copy_to_user(optval, &val, olr)) if (copy_to_user(optval, &val, olr))
return -EFAULT; return -EFAULT;
return 0; return 0;
@ -1707,7 +1739,6 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
if (!vif->dev) if (!vif->dev)
goto out_free; goto out_free;
#ifdef CONFIG_IP_PIMSM
if (vif->flags & VIFF_REGISTER) { if (vif->flags & VIFF_REGISTER) {
vif->pkt_out++; vif->pkt_out++;
vif->bytes_out += skb->len; vif->bytes_out += skb->len;
@ -1716,7 +1747,6 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
ipmr_cache_report(mrt, skb, vifi, IGMPMSG_WHOLEPKT); ipmr_cache_report(mrt, skb, vifi, IGMPMSG_WHOLEPKT);
goto out_free; goto out_free;
} }
#endif
if (vif->flags & VIFF_TUNNEL) { if (vif->flags & VIFF_TUNNEL) {
rt = ip_route_output_ports(net, &fl4, NULL, rt = ip_route_output_ports(net, &fl4, NULL,
@ -2047,48 +2077,6 @@ dont_forward:
return 0; return 0;
} }
#ifdef CONFIG_IP_PIMSM
/* called with rcu_read_lock() */
static int __pim_rcv(struct mr_table *mrt, struct sk_buff *skb,
unsigned int pimlen)
{
struct net_device *reg_dev = NULL;
struct iphdr *encap;
encap = (struct iphdr *)(skb_transport_header(skb) + pimlen);
/*
* Check that:
* a. packet is really sent to a multicast group
* b. packet is not a NULL-REGISTER
* c. packet is not truncated
*/
if (!ipv4_is_multicast(encap->daddr) ||
encap->tot_len == 0 ||
ntohs(encap->tot_len) + pimlen > skb->len)
return 1;
read_lock(&mrt_lock);
if (mrt->mroute_reg_vif_num >= 0)
reg_dev = mrt->vif_table[mrt->mroute_reg_vif_num].dev;
read_unlock(&mrt_lock);
if (!reg_dev)
return 1;
skb->mac_header = skb->network_header;
skb_pull(skb, (u8 *)encap - skb->data);
skb_reset_network_header(skb);
skb->protocol = htons(ETH_P_IP);
skb->ip_summed = CHECKSUM_NONE;
skb_tunnel_rx(skb, reg_dev, dev_net(reg_dev));
netif_rx(skb);
return NET_RX_SUCCESS;
}
#endif
#ifdef CONFIG_IP_PIMSM_V1 #ifdef CONFIG_IP_PIMSM_V1
/* /*
* Handle IGMP messages of PIMv1 * Handle IGMP messages of PIMv1