--- zzzz-none-000/linux-4.1.38/drivers/net/ppp/ppp_generic.c 2017-01-18 18:48:06.000000000 +0000 +++ bcm63-7582-715/linux-4.1.38/drivers/net/ppp/ppp_generic.c 2020-11-25 10:06:48.000000000 +0000 @@ -54,6 +54,10 @@ #include #include +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) +#include +#endif + #define PPP_VERSION "2.4.2" /* @@ -70,6 +74,12 @@ #define MPHDRLEN 6 /* multilink protocol header length */ #define MPHDRLEN_SSN 4 /* ditto with short sequence numbers */ +#if defined(CONFIG_BCM_KF_PPP) +#define FIELD0 4 /* ppp device number ppp0, ppp1, the third digit (max 16) */ +#define FIELD1 8 /* if 0, default mode, 1 vlan mux, 2 msc */ +#define FIELD2 19 /* if FILED1 is 0, add no extension, 1 add vlan id, 2 add conId for msc */ +#endif + /* * An instance of /dev/ppp can be associated with either a ppp * interface unit or a ppp channel. In both cases, file->private_data @@ -134,6 +144,10 @@ unsigned long last_recv; /* jiffies when last pkt rcvd a0 */ struct net_device *dev; /* network interface device a4 */ int closing; /* is device closing down? a8 */ +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + struct rtnl_link_stats64 cstats; /* Cummulative Blog Stats -- should replace with BlogStats_t when blog-stats are 64bit */ +#endif + #ifdef CONFIG_PPP_MULTILINK int nxchan; /* next channel to send something on */ u32 nxseq; /* next sequence number to send */ @@ -494,6 +508,10 @@ goto out; } +#if defined(CONFIG_BCM_KF_PPP) + skb->mark = 7; /* mark with the highest subpriority value */ +#endif + skb_queue_tail(&pf->xq, skb); switch (pf->kind) { @@ -570,8 +588,15 @@ struct npioctl npi; int unit, cflags; struct slcompress *vj; +#if defined(CONFIG_BCM_KF_PPP) && defined(CONFIG_BCM_KF_NETDEV_PATH) + char real_dev_name[IFNAMSIZ]; + struct net_device *real_dev; +#endif void __user *argp = (void __user *)arg; int __user *p = argp; +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + BlogStats_t bStats; +#endif mutex_lock(&ppp_mutex); @@ -653,6 +678,38 @@ err = 0; break; +#if defined(CONFIG_BCM_KF_PPP) && defined(CONFIG_BCM_KF_NETDEV_PATH) + case PPPIOCSREALDEV: + /* 64 bit compatibility handling is not needed since the dev_name string + is passed as a pointer in the arg. Compatibility handling is needed + only when a pointer to a structure is passed in the arg field and + the members of the structure require a 32bit<->64 bit conversion */ + copy_from_user(real_dev_name, argp, IFNAMSIZ); + real_dev_name[IFNAMSIZ-1] = '\0'; /* NULL terminate, just in case */ + + real_dev = dev_get_by_name(&init_net, real_dev_name); + if(real_dev == NULL) + { + printk(KERN_ERR "PPP: Invalid Real Device Name : %s\n", real_dev_name); + err = -EINVAL; + break; + } + + err = netdev_path_add(ppp->dev, real_dev); + if(err) + { + printk(KERN_ERR "PPP: Failed to add %s to Interface path (%d)", + ppp->dev->name, err); + dev_put(real_dev); + } + else + { + netdev_path_dump(ppp->dev); + } + + break; +#endif + case PPPIOCSFLAGS: if (get_user(val, p)) break; @@ -700,6 +757,16 @@ break; case PPPIOCGIDLE: +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + memset(&bStats, 0, sizeof(BlogStats_t)); + blog_lock(); + blog_notify(FETCH_NETIF_STATS, (void*)ppp->dev, (unsigned long)&bStats, BLOG_PARAM2_NO_CLEAR); + blog_unlock(); + if(bStats.tx_packets) + ppp->last_xmit = jiffies; + if(bStats.rx_packets) + ppp->last_recv = jiffies; +#endif idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ; idle.recv_idle = (jiffies - ppp->last_recv) / HZ; if (copy_to_user(argp, &idle, sizeof(idle))) @@ -889,14 +956,14 @@ } static const struct file_operations ppp_device_fops = { - .owner = THIS_MODULE, - .read = ppp_read, - .write = ppp_write, - .poll = ppp_poll, + .owner = THIS_MODULE, + .read = ppp_read, + .write = ppp_write, + .poll = ppp_poll, .unlocked_ioctl = ppp_ioctl, - .open = ppp_open, - .release = ppp_release, - .llseek = noop_llseek, + .open = ppp_open, + .release = ppp_release, + .llseek = noop_llseek, }; static __net_init int ppp_init_net(struct net *net) @@ -1015,6 +1082,76 @@ return NETDEV_TX_OK; } +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) +/* note: BLOG changes for read-only statistic data. */ + +static inline struct rtnl_link_stats64 *ppp_dev_get_cstats(struct net_device *dev) +{ + struct ppp *ppp = netdev_priv(dev); + + return &ppp->cstats; +} + + +static void ppp_dev_update_stats(struct net_device * dev_p, + BlogStats_t * blogStats_p) +{ + if ( dev_p == (struct net_device *)NULL ) + return; + + struct rtnl_link_stats64 *cStats_p = ppp_dev_get_cstats(dev_p); + + cStats_p->rx_packets += blogStats_p->rx_packets; + cStats_p->tx_packets += blogStats_p->tx_packets; + cStats_p->rx_bytes += blogStats_p->rx_bytes; + cStats_p->tx_bytes += blogStats_p->tx_bytes; + cStats_p->multicast += blogStats_p->multicast; + +#if defined(CONFIG_BCM_KF_EXTSTATS) + /* Extended statistics */ + cStats_p->tx_multicast_packets += blogStats_p->tx_multicast_packets; + cStats_p->rx_multicast_bytes += blogStats_p->rx_multicast_bytes; + cStats_p->tx_multicast_bytes += blogStats_p->tx_multicast_bytes; + + /* NOTE: There are no broadcast packets in BlogStats_t since the + flowcache doesn't accelerate broadcast. Thus, they aren't added here */ +#endif + + return; +} + +static void ppp_dev_clear_stats(struct net_device * dev_p) +{ + struct rtnl_link_stats64 *cStats_p; + struct ppp *ppp; + + if ( dev_p == (struct net_device *)NULL ) + return; + ppp = netdev_priv(dev_p); + + ppp_recv_lock(ppp); + ppp->stats64.rx_packets = 0; + ppp->stats64.rx_bytes = 0; + ppp_recv_unlock(ppp); + + ppp_xmit_lock(ppp); + ppp->stats64.tx_packets = 0; + ppp->stats64.tx_bytes = 0; + ppp_xmit_unlock(ppp); + + memset(&dev_p->stats, 0, sizeof(dev_p->stats)); + + cStats_p = ppp_dev_get_cstats(dev_p); + memset(cStats_p, 0, sizeof(*cStats_p)); + + blog_lock(); + blog_notify(FETCH_NETIF_STATS, (void*)dev_p, 0, BLOG_PARAM2_DO_CLEAR); + blog_unlock(); + + return; +} +#endif /* defined(CONFIG_BLOG) */ + static int ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { @@ -1057,6 +1194,59 @@ return err; } +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) +static void ppp_addStats(struct rtnl_link_stats64 *cStats64_p, + struct rtnl_link_stats64 *stats64_p) +{ + /* NOTE : For now the usage of this function is limited to + * adding blog specific counters only, otherwise we should add + * all the stats. */ + cStats64_p->rx_packets += stats64_p->rx_packets ; + cStats64_p->tx_packets += stats64_p->tx_packets ; + cStats64_p->multicast += stats64_p->multicast ; + cStats64_p->rx_bytes += stats64_p->rx_bytes ; + cStats64_p->tx_bytes += stats64_p->tx_bytes ; + +#if defined(CONFIG_BCM_KF_EXTSTATS) + cStats64_p->rx_multicast_bytes += stats64_p->rx_multicast_bytes ; + cStats64_p->tx_multicast_bytes += stats64_p->tx_multicast_bytes ; + cStats64_p->tx_multicast_packets += stats64_p->tx_multicast_packets ; +#endif + +} + +static void ppp_addBlogStats(struct rtnl_link_stats64 *dStats64_p, + BlogStats_t *blogStats_p) +{ + dStats64_p->rx_packets += blogStats_p->rx_packets ; + dStats64_p->tx_packets += blogStats_p->tx_packets ; + dStats64_p->multicast += blogStats_p->multicast ; + dStats64_p->rx_bytes += blogStats_p->rx_bytes ; + dStats64_p->tx_bytes += blogStats_p->tx_bytes ; + +#if defined(CONFIG_BCM_KF_EXTSTATS) + dStats64_p->rx_multicast_bytes += blogStats_p->rx_multicast_bytes ; + dStats64_p->tx_multicast_bytes += blogStats_p->tx_multicast_bytes ; + dStats64_p->tx_multicast_packets += blogStats_p->tx_multicast_packets ; + /* NOTE: There are no broadcast packets in BlogStats_t since the + flowcache doesn't accelerate broadcast. Thus, they aren't added here */ +#endif + +} + +static void ppp_devCollectBlogRunningStats(struct net_device * dev_p, + BlogStats_t *bStats_p) +{ + if ( dev_p == (struct net_device *)NULL ) + return ; + + blog_lock(); + blog_notify(FETCH_NETIF_STATS, (void*)dev_p, + (unsigned long)bStats_p, BLOG_PARAM2_NO_CLEAR); + blog_unlock(); + return; +} +#endif static struct rtnl_link_stats64* ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) @@ -1079,9 +1269,19 @@ stats64->tx_dropped = dev->stats.tx_dropped; stats64->rx_length_errors = dev->stats.rx_length_errors; +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + { + BlogStats_t bStats; + memset(&bStats, 0, sizeof(BlogStats_t)); + + ppp_devCollectBlogRunningStats(dev, &bStats); + ppp_addBlogStats(stats64, &bStats); + ppp_addStats(stats64, &ppp->cstats); + } +#endif /* CONFIG_BLOG */ + return stats64; } - static struct lock_class_key ppp_tx_busylock; static int ppp_dev_init(struct net_device *dev) { @@ -1105,8 +1305,21 @@ dev->tx_queue_len = 3; dev->type = ARPHRD_PPP; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; +#if defined(CONFIG_BCM_KF_WANDEV) + dev->priv_flags = IFF_WANDEV; +#endif +#if defined(CONFIG_BCM_KF_PPP) + dev->priv_flags |= IFF_PPP; +#endif dev->features |= NETIF_F_NETNS_LOCAL; netif_keep_dst(dev); +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + dev->put_stats = ppp_dev_update_stats; + dev->clr_stats = ppp_dev_clear_stats; +#if defined(CONFIG_BCM_KF_EXTSTATS) + dev->features |= NETIF_F_EXTSTATS; +#endif +#endif } /* @@ -1188,6 +1401,54 @@ return new_skb; } +#if defined(CONFIG_BCM_KF_PPP) +/* +brcm_on_demand_filter(...) and ppp_send_frame(...) are protected for SMP+Preempt safety +by ppp_xmit_lock(ppp) => spin_lock_bh(&(ppp)->wlock) and ppp_xmit_unlock(ppp) => spin_unlock_bh(&(ppp)->wlock). +*/ + +/* + * Excluding timestamp for packet generated from ADSL modem + * these include WAN-side RIP,dnsprobe + */ +static int +brcm_on_demand_filter(char *data) +{ + unsigned short udp_port=0; + +#if 0 + char cmd; + + printk("%02x%02x%02x%02x\n%02x%02x%02x%02x\n",data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9]); + printk("%02x%02x%02x%02x\n%02x%02x%02x%02x\n",data[10],data[11],data[12],data[13],data[14],data[15],data[16],data[17]); + printk("%02x%02x%02x%02x\n",data[18],data[19],data[20],data[21]); +#endif + + if ( data[11] == 0x2 ) /* IGMP */ + return 0; + if ( data[11] == 0x11 ) { /* UDP */ + udp_port= (data[24]<< 8) + data[25]; + if ( udp_port == 123 ) { /* ntpclient */ + return 0; + } + if ( udp_port == 53 ) { + if ( data[45] == 'r' && data[46] == 'o' && data[47] == 'o' && data[48] =='t') + + return 0; + } + else if (udp_port == 520) { /* RIP */ +#if 0 + cmd = data[30]; // 1=request, 2=reply + if ( cmd == 1) +#endif + return 0; + } + } + + return 1; +} +#endif + /* * Compress and send a frame. * The caller should have locked the xmit path, @@ -1200,6 +1461,15 @@ struct sk_buff *new_skb; int len; unsigned char *cp; +#if defined(CONFIG_BCM_KF_PPP) + unsigned char *data; + int timestamp = 1; + + if ( proto == PPP_IP) { + data = skb->data; + timestamp = brcm_on_demand_filter(data); + } +#endif if (proto < 0x8000) { #ifdef CONFIG_PPP_FILTER @@ -1208,7 +1478,7 @@ a four-byte PPP header on each packet */ *skb_push(skb, 2) = 1; if (ppp->pass_filter && - BPF_PROG_RUN(ppp->pass_filter, skb) == 0) { + BPF_PROG_RUN(ppp->pass_filter, skb) == 0) { if (ppp->debug & 1) netdev_printk(KERN_DEBUG, ppp->dev, "PPP: outbound frame " @@ -1218,18 +1488,35 @@ } /* if this packet passes the active filter, record the time */ if (!(ppp->active_filter && - BPF_PROG_RUN(ppp->active_filter, skb) == 0)) + BPF_PROG_RUN(ppp->active_filter, skb) == 0)) +#if defined(CONFIG_BCM_KF_PPP) + if (timestamp) +#endif ppp->last_xmit = jiffies; skb_pull(skb, 2); #else /* for data packets, record the time */ +#if defined(CONFIG_BCM_KF_PPP) + if (timestamp) +#endif ppp->last_xmit = jiffies; #endif /* CONFIG_PPP_FILTER */ } +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + blog_lock(); + blog_link(IF_DEVICE, blog_ptr(skb), (void*)ppp->dev, DIR_TX, skb->len - 2 ); + blog_unlock(); +#endif + ++ppp->stats64.tx_packets; ppp->stats64.tx_bytes += skb->len - 2; +#if defined(CONFIG_BCM_KF_EXTSTATS) + ppp->dev->stats.tx_packets++; + ppp->dev->stats.tx_bytes += skb->len - 2; +#endif + switch (proto) { case PPP_IP: if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0) @@ -1293,6 +1580,10 @@ if (ppp->flags & SC_LOOP_TRAFFIC) { if (ppp->file.rq.qlen > PPP_MAX_RQLEN) goto drop; +#if defined(CONFIG_BCM_KF_PPP) + if (!timestamp) + goto drop; +#endif skb_queue_tail(&ppp->file.rq, skb); wake_up_interruptible(&ppp->file.rwait); return; @@ -1739,11 +2030,42 @@ slhc_toss(ppp->vj); } +#if defined(CONFIG_BCM_KF_PPP) +/* +note: brcm_mcast_filter(...) and ppp_receive_nonmp_frame(...) are protected for SMP+Preempt safety +by ppp_recv_lock(ppp) => spin_lock_bh(&(ppp)->rlock) and ppp_recv_unlock(ppp) => spin_unlock_bh(&(ppp)->rlock). +*/ + +static int +brcm_mcast_filter(char *data) +{ + struct iphdr *encap; + + encap = (struct iphdr *)(data + 2); + if ( ipv4_is_multicast(encap->daddr)) { + if ( !ipv4_is_local_multicast(encap->daddr)) { // real mcast data + //printk("bcm_mcast_filer: 0x%x \n",encap->daddr); + return 1; // no timestamp + } + else + return 0; + } + else + return 0; +} +#endif + + static void ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) { struct sk_buff *ns; int proto, len, npi; +#if defined(CONFIG_BCM_KF_PPP) + struct sk_buff *tmp; + int timestamp=0; + unsigned char *data; +#endif /* * Decompress the frame, if compressed. @@ -1758,6 +2080,13 @@ goto err; proto = PPP_PROTO(skb); + +#if defined(CONFIG_BCM_KF_PPP) + if (proto == PPP_IP) { + data = skb->data; + timestamp = brcm_mcast_filter(data); + } +#endif switch (proto) { case PPP_VJC_COMP: /* decompress VJ compressed packets */ @@ -1816,9 +2145,20 @@ break; } +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + blog_lock(); + blog_link(IF_DEVICE, blog_ptr(skb), (void*)ppp->dev, DIR_RX, skb->len - 2 ); + blog_unlock(); +#endif + ++ppp->stats64.rx_packets; ppp->stats64.rx_bytes += skb->len - 2; +#if defined(CONFIG_BCM_KF_EXTSTATS) + ppp->dev->stats.rx_packets++; + ppp->dev->stats.rx_bytes += skb->len - 2; +#endif + npi = proto_to_npindex(proto); if (npi < 0) { /* control or unknown frame - pass it to pppd */ @@ -1833,6 +2173,37 @@ } else { /* network protocol frame - give it to the kernel */ +#if defined(CONFIG_BCM_KF_PPP) +#ifdef CONFIG_PPP_FILTER + /* check if the packet passes the pass and active filters */ + /* the filter instructions are constructed assuming + a four-byte PPP header on each packet */ + if (skb_headroom(skb) < 2) { + tmp = alloc_skb(skb->len+2,GFP_ATOMIC); + skb_reserve(tmp, 2); + memcpy(skb_put(tmp, skb->len), skb->data, skb->len); + kfree_skb(skb); + skb = tmp; + } + *skb_push(skb, 2) = 0; + if (ppp->pass_filter && + BPF_PROG_RUN(ppp->pass_filter, skb) == 0) { + if (ppp->debug & 1) + printk(KERN_DEBUG "PPP: inbound frame not passed\n"); + kfree_skb(skb); + return; + } + if (!(ppp->active_filter && + BPF_PROG_RUN(ppp->active_filter, skb) == 0)) + if (timestamp) + ppp->last_recv = jiffies; + skb_pull(skb, 2); +#else + if (timestamp) + ppp->last_recv = jiffies; +#endif /* CONFIG_PPP_FILTER */ + +#else #ifdef CONFIG_PPP_FILTER /* check if the packet passes the pass and active filters */ /* the filter instructions are constructed assuming @@ -1858,6 +2229,7 @@ } else #endif /* CONFIG_PPP_FILTER */ ppp->last_recv = jiffies; +#endif /* CONFIG_BCM_KF_PPP */ if ((ppp->dev->flags & IFF_UP) == 0 || ppp->npmode[npi] != NPMODE_PASS) { @@ -2648,6 +3020,25 @@ st->p.ppp_opackets = ppp->stats64.tx_packets; st->p.ppp_oerrors = ppp->dev->stats.tx_errors; st->p.ppp_obytes = ppp->stats64.tx_bytes; + +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + { + BlogStats_t bStats; + struct rtnl_link_stats64 cstats; + memset(&bStats, 0, sizeof(bStats)); + memset(&cstats, 0, sizeof(cstats)); + + ppp_devCollectBlogRunningStats(ppp->dev, &bStats); + ppp_addBlogStats(&cstats, &bStats); + ppp_addStats(&cstats, &ppp->cstats); + + st->p.ppp_ipackets += cstats.rx_packets; + st->p.ppp_ibytes += cstats.rx_bytes; + st->p.ppp_opackets += cstats.tx_packets; + st->p.ppp_obytes += cstats.tx_bytes; + } +#endif + if (!vj) return; st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; @@ -2665,6 +3056,10 @@ * and for initialization. */ +#if defined(CONFIG_BCM_KF_PPP) +/* note: ppp_create_interface(...) is protected by lock_kernel() and unlock_kernel() in ppp_unattached_ioctl(...). */ +#endif + /* * Create a new ppp interface unit. Fails if it can't allocate memory * or if there is already a unit with the requested number. @@ -2739,7 +3134,43 @@ /* Initialize the new ppp unit */ ppp->file.index = unit; + +#if defined(CONFIG_BCM_KF_PPP) + if (unit >= 0) + { + unsigned num[3]={0,0,0}; + unsigned u=unit; + + /* req_name will beused as ifname and for + * num[1] == 0: default connection mdoe: ppp0, ppp1... + * num[1] == 1: vlanMux mode: ppp0.100, ppp1.200... + * num[1] == 2: msc (multiple service mode) ppp0_1, ppp1_3... + * num[1] == 3: pppoa0, pppoa1... + * + */ + num[0] = u<<(32-(FIELD2+FIELD1+FIELD0))>>(32-FIELD0); + num[1] = u<<(32-(FIELD2+FIELD1))>>(32-FIELD1); + num[2] = u<<(32-(FIELD2))>>(32-FIELD2); + if (num[1] == 0) + { + sprintf(dev->name, "ppp%d", num[0]); + } + else if (num[1] == 1) /* vlan mux */ + { + sprintf(dev->name, "ppp%d.%d", num[0], num[2]); + } + else if (num[1] == 2) /* msc */ + { + sprintf(dev->name, "ppp%d_%d", num[0], num[2]); + } + else if (num[1] == 3) /* pppoa */ + { + sprintf(dev->name, "pppoa%d", num[0]); + } + } +#else sprintf(dev->name, "ppp%d", unit); +#endif ret = register_netdev(dev); if (ret != 0) { @@ -2792,6 +3223,20 @@ /* This will call dev_close() for us. */ ppp_lock(ppp); if (!ppp->closing) { +#if defined(CONFIG_BCM_KF_PPP) + int err; + struct net_device *next_dev; + next_dev = netdev_path_next_dev(ppp->dev); + err = netdev_path_remove(ppp->dev); + if(err) + { + printk(KERN_ERR "PPP: Failed to remove %s from Interface path (%d)", + ppp->dev->name, err); + netdev_path_dump(ppp->dev); + } + if(next_dev != NULL) + dev_put(next_dev); +#endif ppp->closing = 1; ppp_unlock(ppp); unregister_netdev(ppp->dev); @@ -3019,6 +3464,32 @@ return idr_find(p, n); } +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) +int +ppp_rcv_decomp_run(struct ppp_channel *chan) +{ + struct channel *ch; + struct ppp *ppp; + + if (!chan) + return 0; + ch = chan->ppp; + if (!ch) + return 0; + ppp = ch->ppp; + if (!ppp) + return 0; + + pr_info("%s: flags 0x%x xstate 0x%x rstate 0x%x\n", + __FUNCTION__, ppp->flags, ppp->xstate, ppp->rstate); + + if (ppp->rstate & SC_DECOMP_RUN) + return 1; + else + return 0; +} +#endif + /* Module/initialization stuff */ module_init(ppp_init); @@ -3035,6 +3506,9 @@ EXPORT_SYMBOL(ppp_output_wakeup); EXPORT_SYMBOL(ppp_register_compressor); EXPORT_SYMBOL(ppp_unregister_compressor); +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) +EXPORT_SYMBOL(ppp_rcv_decomp_run); +#endif MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0); MODULE_ALIAS("devname:ppp");