diff options
Diffstat (limited to 'drivers/net/ppp/ppp_generic.c')
-rw-r--r-- | drivers/net/ppp/ppp_generic.c | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index f226db4616b7..5489c0ec1d9a 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -1103,6 +1103,15 @@ static int ppp_nl_newlink(struct net *src_net, struct net_device *dev, } conf.file = file; + + /* Don't use device name generated by the rtnetlink layer when ifname + * isn't specified. Let ppp_dev_configure() set the device name using + * the PPP unit identifer as suffix (i.e. ppp<unit_id>). This allows + * userspace to infer the device name using to the PPPIOCGUNIT ioctl. + */ + if (!tb[IFLA_IFNAME]) + conf.ifname_is_set = false; + err = ppp_dev_configure(src_net, dev, &conf); out_unlock: @@ -1354,6 +1363,8 @@ static void ppp_setup(struct net_device *dev) dev->netdev_ops = &ppp_netdev_ops; SET_NETDEV_DEVTYPE(dev, &ppp_type); + dev->features |= NETIF_F_LLTX; + dev->hard_header_len = PPP_HDRLEN; dev->mtu = PPP_MRU; dev->addr_len = 0; @@ -1367,12 +1378,8 @@ static void ppp_setup(struct net_device *dev) * Transmit-side routines. */ -/* - * Called to do any work queued up on the transmit side - * that can now be done. - */ -static void -ppp_xmit_process(struct ppp *ppp) +/* Called to do any work queued up on the transmit side that can now be done */ +static void __ppp_xmit_process(struct ppp *ppp) { struct sk_buff *skb; @@ -1392,6 +1399,30 @@ ppp_xmit_process(struct ppp *ppp) ppp_xmit_unlock(ppp); } +static DEFINE_PER_CPU(int, ppp_xmit_recursion); + +static void ppp_xmit_process(struct ppp *ppp) +{ + local_bh_disable(); + + if (unlikely(__this_cpu_read(ppp_xmit_recursion))) + goto err; + + __this_cpu_inc(ppp_xmit_recursion); + __ppp_xmit_process(ppp); + __this_cpu_dec(ppp_xmit_recursion); + + local_bh_enable(); + + return; + +err: + local_bh_enable(); + + if (net_ratelimit()) + netdev_err(ppp->dev, "recursion detected\n"); +} + static inline struct sk_buff * pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) { @@ -1847,11 +1878,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) } #endif /* CONFIG_PPP_MULTILINK */ -/* - * Try to send data out on a channel. - */ -static void -ppp_channel_push(struct channel *pch) +/* Try to send data out on a channel */ +static void __ppp_channel_push(struct channel *pch) { struct sk_buff *skb; struct ppp *ppp; @@ -1876,11 +1904,22 @@ ppp_channel_push(struct channel *pch) read_lock_bh(&pch->upl); ppp = pch->ppp; if (ppp) - ppp_xmit_process(ppp); + __ppp_xmit_process(ppp); read_unlock_bh(&pch->upl); } } +static void ppp_channel_push(struct channel *pch) +{ + local_bh_disable(); + + __this_cpu_inc(ppp_xmit_recursion); + __ppp_channel_push(pch); + __this_cpu_dec(ppp_xmit_recursion); + + local_bh_enable(); +} + /* * Receive-side routines. */ |