1*1da177e4SLinus Torvalds /* net/sched/sch_teql.c "True" (or "trivial") link equalizer. 2*1da177e4SLinus Torvalds * 3*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 4*1da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 5*1da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 6*1da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 7*1da177e4SLinus Torvalds * 8*1da177e4SLinus Torvalds * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 9*1da177e4SLinus Torvalds */ 10*1da177e4SLinus Torvalds 11*1da177e4SLinus Torvalds #include <linux/module.h> 12*1da177e4SLinus Torvalds #include <asm/uaccess.h> 13*1da177e4SLinus Torvalds #include <asm/system.h> 14*1da177e4SLinus Torvalds #include <linux/bitops.h> 15*1da177e4SLinus Torvalds #include <linux/types.h> 16*1da177e4SLinus Torvalds #include <linux/kernel.h> 17*1da177e4SLinus Torvalds #include <linux/sched.h> 18*1da177e4SLinus Torvalds #include <linux/string.h> 19*1da177e4SLinus Torvalds #include <linux/mm.h> 20*1da177e4SLinus Torvalds #include <linux/socket.h> 21*1da177e4SLinus Torvalds #include <linux/sockios.h> 22*1da177e4SLinus Torvalds #include <linux/in.h> 23*1da177e4SLinus Torvalds #include <linux/errno.h> 24*1da177e4SLinus Torvalds #include <linux/interrupt.h> 25*1da177e4SLinus Torvalds #include <linux/if_ether.h> 26*1da177e4SLinus Torvalds #include <linux/inet.h> 27*1da177e4SLinus Torvalds #include <linux/netdevice.h> 28*1da177e4SLinus Torvalds #include <linux/etherdevice.h> 29*1da177e4SLinus Torvalds #include <linux/notifier.h> 30*1da177e4SLinus Torvalds #include <linux/init.h> 31*1da177e4SLinus Torvalds #include <net/ip.h> 32*1da177e4SLinus Torvalds #include <net/route.h> 33*1da177e4SLinus Torvalds #include <linux/skbuff.h> 34*1da177e4SLinus Torvalds #include <linux/moduleparam.h> 35*1da177e4SLinus Torvalds #include <net/sock.h> 36*1da177e4SLinus Torvalds #include <net/pkt_sched.h> 37*1da177e4SLinus Torvalds 38*1da177e4SLinus Torvalds /* 39*1da177e4SLinus Torvalds How to setup it. 40*1da177e4SLinus Torvalds ---------------- 41*1da177e4SLinus Torvalds 42*1da177e4SLinus Torvalds After loading this module you will find a new device teqlN 43*1da177e4SLinus Torvalds and new qdisc with the same name. To join a slave to the equalizer 44*1da177e4SLinus Torvalds you should just set this qdisc on a device f.e. 45*1da177e4SLinus Torvalds 46*1da177e4SLinus Torvalds # tc qdisc add dev eth0 root teql0 47*1da177e4SLinus Torvalds # tc qdisc add dev eth1 root teql0 48*1da177e4SLinus Torvalds 49*1da177e4SLinus Torvalds That's all. Full PnP 8) 50*1da177e4SLinus Torvalds 51*1da177e4SLinus Torvalds Applicability. 52*1da177e4SLinus Torvalds -------------- 53*1da177e4SLinus Torvalds 54*1da177e4SLinus Torvalds 1. Slave devices MUST be active devices, i.e., they must raise the tbusy 55*1da177e4SLinus Torvalds signal and generate EOI events. If you want to equalize virtual devices 56*1da177e4SLinus Torvalds like tunnels, use a normal eql device. 57*1da177e4SLinus Torvalds 2. This device puts no limitations on physical slave characteristics 58*1da177e4SLinus Torvalds f.e. it will equalize 9600baud line and 100Mb ethernet perfectly :-) 59*1da177e4SLinus Torvalds Certainly, large difference in link speeds will make the resulting 60*1da177e4SLinus Torvalds eqalized link unusable, because of huge packet reordering. 61*1da177e4SLinus Torvalds I estimate an upper useful difference as ~10 times. 62*1da177e4SLinus Torvalds 3. If the slave requires address resolution, only protocols using 63*1da177e4SLinus Torvalds neighbour cache (IPv4/IPv6) will work over the equalized link. 64*1da177e4SLinus Torvalds Other protocols are still allowed to use the slave device directly, 65*1da177e4SLinus Torvalds which will not break load balancing, though native slave 66*1da177e4SLinus Torvalds traffic will have the highest priority. */ 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds struct teql_master 69*1da177e4SLinus Torvalds { 70*1da177e4SLinus Torvalds struct Qdisc_ops qops; 71*1da177e4SLinus Torvalds struct net_device *dev; 72*1da177e4SLinus Torvalds struct Qdisc *slaves; 73*1da177e4SLinus Torvalds struct list_head master_list; 74*1da177e4SLinus Torvalds struct net_device_stats stats; 75*1da177e4SLinus Torvalds }; 76*1da177e4SLinus Torvalds 77*1da177e4SLinus Torvalds struct teql_sched_data 78*1da177e4SLinus Torvalds { 79*1da177e4SLinus Torvalds struct Qdisc *next; 80*1da177e4SLinus Torvalds struct teql_master *m; 81*1da177e4SLinus Torvalds struct neighbour *ncache; 82*1da177e4SLinus Torvalds struct sk_buff_head q; 83*1da177e4SLinus Torvalds }; 84*1da177e4SLinus Torvalds 85*1da177e4SLinus Torvalds #define NEXT_SLAVE(q) (((struct teql_sched_data*)qdisc_priv(q))->next) 86*1da177e4SLinus Torvalds 87*1da177e4SLinus Torvalds #define FMASK (IFF_BROADCAST|IFF_POINTOPOINT|IFF_BROADCAST) 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds /* "teql*" qdisc routines */ 90*1da177e4SLinus Torvalds 91*1da177e4SLinus Torvalds static int 92*1da177e4SLinus Torvalds teql_enqueue(struct sk_buff *skb, struct Qdisc* sch) 93*1da177e4SLinus Torvalds { 94*1da177e4SLinus Torvalds struct net_device *dev = sch->dev; 95*1da177e4SLinus Torvalds struct teql_sched_data *q = qdisc_priv(sch); 96*1da177e4SLinus Torvalds 97*1da177e4SLinus Torvalds __skb_queue_tail(&q->q, skb); 98*1da177e4SLinus Torvalds if (q->q.qlen <= dev->tx_queue_len) { 99*1da177e4SLinus Torvalds sch->bstats.bytes += skb->len; 100*1da177e4SLinus Torvalds sch->bstats.packets++; 101*1da177e4SLinus Torvalds return 0; 102*1da177e4SLinus Torvalds } 103*1da177e4SLinus Torvalds 104*1da177e4SLinus Torvalds __skb_unlink(skb, &q->q); 105*1da177e4SLinus Torvalds kfree_skb(skb); 106*1da177e4SLinus Torvalds sch->qstats.drops++; 107*1da177e4SLinus Torvalds return NET_XMIT_DROP; 108*1da177e4SLinus Torvalds } 109*1da177e4SLinus Torvalds 110*1da177e4SLinus Torvalds static int 111*1da177e4SLinus Torvalds teql_requeue(struct sk_buff *skb, struct Qdisc* sch) 112*1da177e4SLinus Torvalds { 113*1da177e4SLinus Torvalds struct teql_sched_data *q = qdisc_priv(sch); 114*1da177e4SLinus Torvalds 115*1da177e4SLinus Torvalds __skb_queue_head(&q->q, skb); 116*1da177e4SLinus Torvalds sch->qstats.requeues++; 117*1da177e4SLinus Torvalds return 0; 118*1da177e4SLinus Torvalds } 119*1da177e4SLinus Torvalds 120*1da177e4SLinus Torvalds static struct sk_buff * 121*1da177e4SLinus Torvalds teql_dequeue(struct Qdisc* sch) 122*1da177e4SLinus Torvalds { 123*1da177e4SLinus Torvalds struct teql_sched_data *dat = qdisc_priv(sch); 124*1da177e4SLinus Torvalds struct sk_buff *skb; 125*1da177e4SLinus Torvalds 126*1da177e4SLinus Torvalds skb = __skb_dequeue(&dat->q); 127*1da177e4SLinus Torvalds if (skb == NULL) { 128*1da177e4SLinus Torvalds struct net_device *m = dat->m->dev->qdisc->dev; 129*1da177e4SLinus Torvalds if (m) { 130*1da177e4SLinus Torvalds dat->m->slaves = sch; 131*1da177e4SLinus Torvalds netif_wake_queue(m); 132*1da177e4SLinus Torvalds } 133*1da177e4SLinus Torvalds } 134*1da177e4SLinus Torvalds sch->q.qlen = dat->q.qlen + dat->m->dev->qdisc->q.qlen; 135*1da177e4SLinus Torvalds return skb; 136*1da177e4SLinus Torvalds } 137*1da177e4SLinus Torvalds 138*1da177e4SLinus Torvalds static __inline__ void 139*1da177e4SLinus Torvalds teql_neigh_release(struct neighbour *n) 140*1da177e4SLinus Torvalds { 141*1da177e4SLinus Torvalds if (n) 142*1da177e4SLinus Torvalds neigh_release(n); 143*1da177e4SLinus Torvalds } 144*1da177e4SLinus Torvalds 145*1da177e4SLinus Torvalds static void 146*1da177e4SLinus Torvalds teql_reset(struct Qdisc* sch) 147*1da177e4SLinus Torvalds { 148*1da177e4SLinus Torvalds struct teql_sched_data *dat = qdisc_priv(sch); 149*1da177e4SLinus Torvalds 150*1da177e4SLinus Torvalds skb_queue_purge(&dat->q); 151*1da177e4SLinus Torvalds sch->q.qlen = 0; 152*1da177e4SLinus Torvalds teql_neigh_release(xchg(&dat->ncache, NULL)); 153*1da177e4SLinus Torvalds } 154*1da177e4SLinus Torvalds 155*1da177e4SLinus Torvalds static void 156*1da177e4SLinus Torvalds teql_destroy(struct Qdisc* sch) 157*1da177e4SLinus Torvalds { 158*1da177e4SLinus Torvalds struct Qdisc *q, *prev; 159*1da177e4SLinus Torvalds struct teql_sched_data *dat = qdisc_priv(sch); 160*1da177e4SLinus Torvalds struct teql_master *master = dat->m; 161*1da177e4SLinus Torvalds 162*1da177e4SLinus Torvalds if ((prev = master->slaves) != NULL) { 163*1da177e4SLinus Torvalds do { 164*1da177e4SLinus Torvalds q = NEXT_SLAVE(prev); 165*1da177e4SLinus Torvalds if (q == sch) { 166*1da177e4SLinus Torvalds NEXT_SLAVE(prev) = NEXT_SLAVE(q); 167*1da177e4SLinus Torvalds if (q == master->slaves) { 168*1da177e4SLinus Torvalds master->slaves = NEXT_SLAVE(q); 169*1da177e4SLinus Torvalds if (q == master->slaves) { 170*1da177e4SLinus Torvalds master->slaves = NULL; 171*1da177e4SLinus Torvalds spin_lock_bh(&master->dev->queue_lock); 172*1da177e4SLinus Torvalds qdisc_reset(master->dev->qdisc); 173*1da177e4SLinus Torvalds spin_unlock_bh(&master->dev->queue_lock); 174*1da177e4SLinus Torvalds } 175*1da177e4SLinus Torvalds } 176*1da177e4SLinus Torvalds skb_queue_purge(&dat->q); 177*1da177e4SLinus Torvalds teql_neigh_release(xchg(&dat->ncache, NULL)); 178*1da177e4SLinus Torvalds break; 179*1da177e4SLinus Torvalds } 180*1da177e4SLinus Torvalds 181*1da177e4SLinus Torvalds } while ((prev = q) != master->slaves); 182*1da177e4SLinus Torvalds } 183*1da177e4SLinus Torvalds } 184*1da177e4SLinus Torvalds 185*1da177e4SLinus Torvalds static int teql_qdisc_init(struct Qdisc *sch, struct rtattr *opt) 186*1da177e4SLinus Torvalds { 187*1da177e4SLinus Torvalds struct net_device *dev = sch->dev; 188*1da177e4SLinus Torvalds struct teql_master *m = (struct teql_master*)sch->ops; 189*1da177e4SLinus Torvalds struct teql_sched_data *q = qdisc_priv(sch); 190*1da177e4SLinus Torvalds 191*1da177e4SLinus Torvalds if (dev->hard_header_len > m->dev->hard_header_len) 192*1da177e4SLinus Torvalds return -EINVAL; 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds if (m->dev == dev) 195*1da177e4SLinus Torvalds return -ELOOP; 196*1da177e4SLinus Torvalds 197*1da177e4SLinus Torvalds q->m = m; 198*1da177e4SLinus Torvalds 199*1da177e4SLinus Torvalds skb_queue_head_init(&q->q); 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds if (m->slaves) { 202*1da177e4SLinus Torvalds if (m->dev->flags & IFF_UP) { 203*1da177e4SLinus Torvalds if ((m->dev->flags&IFF_POINTOPOINT && !(dev->flags&IFF_POINTOPOINT)) 204*1da177e4SLinus Torvalds || (m->dev->flags&IFF_BROADCAST && !(dev->flags&IFF_BROADCAST)) 205*1da177e4SLinus Torvalds || (m->dev->flags&IFF_MULTICAST && !(dev->flags&IFF_MULTICAST)) 206*1da177e4SLinus Torvalds || dev->mtu < m->dev->mtu) 207*1da177e4SLinus Torvalds return -EINVAL; 208*1da177e4SLinus Torvalds } else { 209*1da177e4SLinus Torvalds if (!(dev->flags&IFF_POINTOPOINT)) 210*1da177e4SLinus Torvalds m->dev->flags &= ~IFF_POINTOPOINT; 211*1da177e4SLinus Torvalds if (!(dev->flags&IFF_BROADCAST)) 212*1da177e4SLinus Torvalds m->dev->flags &= ~IFF_BROADCAST; 213*1da177e4SLinus Torvalds if (!(dev->flags&IFF_MULTICAST)) 214*1da177e4SLinus Torvalds m->dev->flags &= ~IFF_MULTICAST; 215*1da177e4SLinus Torvalds if (dev->mtu < m->dev->mtu) 216*1da177e4SLinus Torvalds m->dev->mtu = dev->mtu; 217*1da177e4SLinus Torvalds } 218*1da177e4SLinus Torvalds q->next = NEXT_SLAVE(m->slaves); 219*1da177e4SLinus Torvalds NEXT_SLAVE(m->slaves) = sch; 220*1da177e4SLinus Torvalds } else { 221*1da177e4SLinus Torvalds q->next = sch; 222*1da177e4SLinus Torvalds m->slaves = sch; 223*1da177e4SLinus Torvalds m->dev->mtu = dev->mtu; 224*1da177e4SLinus Torvalds m->dev->flags = (m->dev->flags&~FMASK)|(dev->flags&FMASK); 225*1da177e4SLinus Torvalds } 226*1da177e4SLinus Torvalds return 0; 227*1da177e4SLinus Torvalds } 228*1da177e4SLinus Torvalds 229*1da177e4SLinus Torvalds /* "teql*" netdevice routines */ 230*1da177e4SLinus Torvalds 231*1da177e4SLinus Torvalds static int 232*1da177e4SLinus Torvalds __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) 233*1da177e4SLinus Torvalds { 234*1da177e4SLinus Torvalds struct teql_sched_data *q = qdisc_priv(dev->qdisc); 235*1da177e4SLinus Torvalds struct neighbour *mn = skb->dst->neighbour; 236*1da177e4SLinus Torvalds struct neighbour *n = q->ncache; 237*1da177e4SLinus Torvalds 238*1da177e4SLinus Torvalds if (mn->tbl == NULL) 239*1da177e4SLinus Torvalds return -EINVAL; 240*1da177e4SLinus Torvalds if (n && n->tbl == mn->tbl && 241*1da177e4SLinus Torvalds memcmp(n->primary_key, mn->primary_key, mn->tbl->key_len) == 0) { 242*1da177e4SLinus Torvalds atomic_inc(&n->refcnt); 243*1da177e4SLinus Torvalds } else { 244*1da177e4SLinus Torvalds n = __neigh_lookup_errno(mn->tbl, mn->primary_key, dev); 245*1da177e4SLinus Torvalds if (IS_ERR(n)) 246*1da177e4SLinus Torvalds return PTR_ERR(n); 247*1da177e4SLinus Torvalds } 248*1da177e4SLinus Torvalds if (neigh_event_send(n, skb_res) == 0) { 249*1da177e4SLinus Torvalds int err; 250*1da177e4SLinus Torvalds read_lock(&n->lock); 251*1da177e4SLinus Torvalds err = dev->hard_header(skb, dev, ntohs(skb->protocol), n->ha, NULL, skb->len); 252*1da177e4SLinus Torvalds read_unlock(&n->lock); 253*1da177e4SLinus Torvalds if (err < 0) { 254*1da177e4SLinus Torvalds neigh_release(n); 255*1da177e4SLinus Torvalds return -EINVAL; 256*1da177e4SLinus Torvalds } 257*1da177e4SLinus Torvalds teql_neigh_release(xchg(&q->ncache, n)); 258*1da177e4SLinus Torvalds return 0; 259*1da177e4SLinus Torvalds } 260*1da177e4SLinus Torvalds neigh_release(n); 261*1da177e4SLinus Torvalds return (skb_res == NULL) ? -EAGAIN : 1; 262*1da177e4SLinus Torvalds } 263*1da177e4SLinus Torvalds 264*1da177e4SLinus Torvalds static __inline__ int 265*1da177e4SLinus Torvalds teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) 266*1da177e4SLinus Torvalds { 267*1da177e4SLinus Torvalds if (dev->hard_header == NULL || 268*1da177e4SLinus Torvalds skb->dst == NULL || 269*1da177e4SLinus Torvalds skb->dst->neighbour == NULL) 270*1da177e4SLinus Torvalds return 0; 271*1da177e4SLinus Torvalds return __teql_resolve(skb, skb_res, dev); 272*1da177e4SLinus Torvalds } 273*1da177e4SLinus Torvalds 274*1da177e4SLinus Torvalds static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) 275*1da177e4SLinus Torvalds { 276*1da177e4SLinus Torvalds struct teql_master *master = (void*)dev->priv; 277*1da177e4SLinus Torvalds struct Qdisc *start, *q; 278*1da177e4SLinus Torvalds int busy; 279*1da177e4SLinus Torvalds int nores; 280*1da177e4SLinus Torvalds int len = skb->len; 281*1da177e4SLinus Torvalds struct sk_buff *skb_res = NULL; 282*1da177e4SLinus Torvalds 283*1da177e4SLinus Torvalds start = master->slaves; 284*1da177e4SLinus Torvalds 285*1da177e4SLinus Torvalds restart: 286*1da177e4SLinus Torvalds nores = 0; 287*1da177e4SLinus Torvalds busy = 0; 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds if ((q = start) == NULL) 290*1da177e4SLinus Torvalds goto drop; 291*1da177e4SLinus Torvalds 292*1da177e4SLinus Torvalds do { 293*1da177e4SLinus Torvalds struct net_device *slave = q->dev; 294*1da177e4SLinus Torvalds 295*1da177e4SLinus Torvalds if (slave->qdisc_sleeping != q) 296*1da177e4SLinus Torvalds continue; 297*1da177e4SLinus Torvalds if (netif_queue_stopped(slave) || ! netif_running(slave)) { 298*1da177e4SLinus Torvalds busy = 1; 299*1da177e4SLinus Torvalds continue; 300*1da177e4SLinus Torvalds } 301*1da177e4SLinus Torvalds 302*1da177e4SLinus Torvalds switch (teql_resolve(skb, skb_res, slave)) { 303*1da177e4SLinus Torvalds case 0: 304*1da177e4SLinus Torvalds if (spin_trylock(&slave->xmit_lock)) { 305*1da177e4SLinus Torvalds slave->xmit_lock_owner = smp_processor_id(); 306*1da177e4SLinus Torvalds if (!netif_queue_stopped(slave) && 307*1da177e4SLinus Torvalds slave->hard_start_xmit(skb, slave) == 0) { 308*1da177e4SLinus Torvalds slave->xmit_lock_owner = -1; 309*1da177e4SLinus Torvalds spin_unlock(&slave->xmit_lock); 310*1da177e4SLinus Torvalds master->slaves = NEXT_SLAVE(q); 311*1da177e4SLinus Torvalds netif_wake_queue(dev); 312*1da177e4SLinus Torvalds master->stats.tx_packets++; 313*1da177e4SLinus Torvalds master->stats.tx_bytes += len; 314*1da177e4SLinus Torvalds return 0; 315*1da177e4SLinus Torvalds } 316*1da177e4SLinus Torvalds slave->xmit_lock_owner = -1; 317*1da177e4SLinus Torvalds spin_unlock(&slave->xmit_lock); 318*1da177e4SLinus Torvalds } 319*1da177e4SLinus Torvalds if (netif_queue_stopped(dev)) 320*1da177e4SLinus Torvalds busy = 1; 321*1da177e4SLinus Torvalds break; 322*1da177e4SLinus Torvalds case 1: 323*1da177e4SLinus Torvalds master->slaves = NEXT_SLAVE(q); 324*1da177e4SLinus Torvalds return 0; 325*1da177e4SLinus Torvalds default: 326*1da177e4SLinus Torvalds nores = 1; 327*1da177e4SLinus Torvalds break; 328*1da177e4SLinus Torvalds } 329*1da177e4SLinus Torvalds __skb_pull(skb, skb->nh.raw - skb->data); 330*1da177e4SLinus Torvalds } while ((q = NEXT_SLAVE(q)) != start); 331*1da177e4SLinus Torvalds 332*1da177e4SLinus Torvalds if (nores && skb_res == NULL) { 333*1da177e4SLinus Torvalds skb_res = skb; 334*1da177e4SLinus Torvalds goto restart; 335*1da177e4SLinus Torvalds } 336*1da177e4SLinus Torvalds 337*1da177e4SLinus Torvalds if (busy) { 338*1da177e4SLinus Torvalds netif_stop_queue(dev); 339*1da177e4SLinus Torvalds return 1; 340*1da177e4SLinus Torvalds } 341*1da177e4SLinus Torvalds master->stats.tx_errors++; 342*1da177e4SLinus Torvalds 343*1da177e4SLinus Torvalds drop: 344*1da177e4SLinus Torvalds master->stats.tx_dropped++; 345*1da177e4SLinus Torvalds dev_kfree_skb(skb); 346*1da177e4SLinus Torvalds return 0; 347*1da177e4SLinus Torvalds } 348*1da177e4SLinus Torvalds 349*1da177e4SLinus Torvalds static int teql_master_open(struct net_device *dev) 350*1da177e4SLinus Torvalds { 351*1da177e4SLinus Torvalds struct Qdisc * q; 352*1da177e4SLinus Torvalds struct teql_master *m = (void*)dev->priv; 353*1da177e4SLinus Torvalds int mtu = 0xFFFE; 354*1da177e4SLinus Torvalds unsigned flags = IFF_NOARP|IFF_MULTICAST; 355*1da177e4SLinus Torvalds 356*1da177e4SLinus Torvalds if (m->slaves == NULL) 357*1da177e4SLinus Torvalds return -EUNATCH; 358*1da177e4SLinus Torvalds 359*1da177e4SLinus Torvalds flags = FMASK; 360*1da177e4SLinus Torvalds 361*1da177e4SLinus Torvalds q = m->slaves; 362*1da177e4SLinus Torvalds do { 363*1da177e4SLinus Torvalds struct net_device *slave = q->dev; 364*1da177e4SLinus Torvalds 365*1da177e4SLinus Torvalds if (slave == NULL) 366*1da177e4SLinus Torvalds return -EUNATCH; 367*1da177e4SLinus Torvalds 368*1da177e4SLinus Torvalds if (slave->mtu < mtu) 369*1da177e4SLinus Torvalds mtu = slave->mtu; 370*1da177e4SLinus Torvalds if (slave->hard_header_len > LL_MAX_HEADER) 371*1da177e4SLinus Torvalds return -EINVAL; 372*1da177e4SLinus Torvalds 373*1da177e4SLinus Torvalds /* If all the slaves are BROADCAST, master is BROADCAST 374*1da177e4SLinus Torvalds If all the slaves are PtP, master is PtP 375*1da177e4SLinus Torvalds Otherwise, master is NBMA. 376*1da177e4SLinus Torvalds */ 377*1da177e4SLinus Torvalds if (!(slave->flags&IFF_POINTOPOINT)) 378*1da177e4SLinus Torvalds flags &= ~IFF_POINTOPOINT; 379*1da177e4SLinus Torvalds if (!(slave->flags&IFF_BROADCAST)) 380*1da177e4SLinus Torvalds flags &= ~IFF_BROADCAST; 381*1da177e4SLinus Torvalds if (!(slave->flags&IFF_MULTICAST)) 382*1da177e4SLinus Torvalds flags &= ~IFF_MULTICAST; 383*1da177e4SLinus Torvalds } while ((q = NEXT_SLAVE(q)) != m->slaves); 384*1da177e4SLinus Torvalds 385*1da177e4SLinus Torvalds m->dev->mtu = mtu; 386*1da177e4SLinus Torvalds m->dev->flags = (m->dev->flags&~FMASK) | flags; 387*1da177e4SLinus Torvalds netif_start_queue(m->dev); 388*1da177e4SLinus Torvalds return 0; 389*1da177e4SLinus Torvalds } 390*1da177e4SLinus Torvalds 391*1da177e4SLinus Torvalds static int teql_master_close(struct net_device *dev) 392*1da177e4SLinus Torvalds { 393*1da177e4SLinus Torvalds netif_stop_queue(dev); 394*1da177e4SLinus Torvalds return 0; 395*1da177e4SLinus Torvalds } 396*1da177e4SLinus Torvalds 397*1da177e4SLinus Torvalds static struct net_device_stats *teql_master_stats(struct net_device *dev) 398*1da177e4SLinus Torvalds { 399*1da177e4SLinus Torvalds struct teql_master *m = (void*)dev->priv; 400*1da177e4SLinus Torvalds return &m->stats; 401*1da177e4SLinus Torvalds } 402*1da177e4SLinus Torvalds 403*1da177e4SLinus Torvalds static int teql_master_mtu(struct net_device *dev, int new_mtu) 404*1da177e4SLinus Torvalds { 405*1da177e4SLinus Torvalds struct teql_master *m = (void*)dev->priv; 406*1da177e4SLinus Torvalds struct Qdisc *q; 407*1da177e4SLinus Torvalds 408*1da177e4SLinus Torvalds if (new_mtu < 68) 409*1da177e4SLinus Torvalds return -EINVAL; 410*1da177e4SLinus Torvalds 411*1da177e4SLinus Torvalds q = m->slaves; 412*1da177e4SLinus Torvalds if (q) { 413*1da177e4SLinus Torvalds do { 414*1da177e4SLinus Torvalds if (new_mtu > q->dev->mtu) 415*1da177e4SLinus Torvalds return -EINVAL; 416*1da177e4SLinus Torvalds } while ((q=NEXT_SLAVE(q)) != m->slaves); 417*1da177e4SLinus Torvalds } 418*1da177e4SLinus Torvalds 419*1da177e4SLinus Torvalds dev->mtu = new_mtu; 420*1da177e4SLinus Torvalds return 0; 421*1da177e4SLinus Torvalds } 422*1da177e4SLinus Torvalds 423*1da177e4SLinus Torvalds static __init void teql_master_setup(struct net_device *dev) 424*1da177e4SLinus Torvalds { 425*1da177e4SLinus Torvalds struct teql_master *master = dev->priv; 426*1da177e4SLinus Torvalds struct Qdisc_ops *ops = &master->qops; 427*1da177e4SLinus Torvalds 428*1da177e4SLinus Torvalds master->dev = dev; 429*1da177e4SLinus Torvalds ops->priv_size = sizeof(struct teql_sched_data); 430*1da177e4SLinus Torvalds 431*1da177e4SLinus Torvalds ops->enqueue = teql_enqueue; 432*1da177e4SLinus Torvalds ops->dequeue = teql_dequeue; 433*1da177e4SLinus Torvalds ops->requeue = teql_requeue; 434*1da177e4SLinus Torvalds ops->init = teql_qdisc_init; 435*1da177e4SLinus Torvalds ops->reset = teql_reset; 436*1da177e4SLinus Torvalds ops->destroy = teql_destroy; 437*1da177e4SLinus Torvalds ops->owner = THIS_MODULE; 438*1da177e4SLinus Torvalds 439*1da177e4SLinus Torvalds dev->open = teql_master_open; 440*1da177e4SLinus Torvalds dev->hard_start_xmit = teql_master_xmit; 441*1da177e4SLinus Torvalds dev->stop = teql_master_close; 442*1da177e4SLinus Torvalds dev->get_stats = teql_master_stats; 443*1da177e4SLinus Torvalds dev->change_mtu = teql_master_mtu; 444*1da177e4SLinus Torvalds dev->type = ARPHRD_VOID; 445*1da177e4SLinus Torvalds dev->mtu = 1500; 446*1da177e4SLinus Torvalds dev->tx_queue_len = 100; 447*1da177e4SLinus Torvalds dev->flags = IFF_NOARP; 448*1da177e4SLinus Torvalds dev->hard_header_len = LL_MAX_HEADER; 449*1da177e4SLinus Torvalds SET_MODULE_OWNER(dev); 450*1da177e4SLinus Torvalds } 451*1da177e4SLinus Torvalds 452*1da177e4SLinus Torvalds static LIST_HEAD(master_dev_list); 453*1da177e4SLinus Torvalds static int max_equalizers = 1; 454*1da177e4SLinus Torvalds module_param(max_equalizers, int, 0); 455*1da177e4SLinus Torvalds MODULE_PARM_DESC(max_equalizers, "Max number of link equalizers"); 456*1da177e4SLinus Torvalds 457*1da177e4SLinus Torvalds static int __init teql_init(void) 458*1da177e4SLinus Torvalds { 459*1da177e4SLinus Torvalds int i; 460*1da177e4SLinus Torvalds int err = -ENODEV; 461*1da177e4SLinus Torvalds 462*1da177e4SLinus Torvalds for (i = 0; i < max_equalizers; i++) { 463*1da177e4SLinus Torvalds struct net_device *dev; 464*1da177e4SLinus Torvalds struct teql_master *master; 465*1da177e4SLinus Torvalds 466*1da177e4SLinus Torvalds dev = alloc_netdev(sizeof(struct teql_master), 467*1da177e4SLinus Torvalds "teql%d", teql_master_setup); 468*1da177e4SLinus Torvalds if (!dev) { 469*1da177e4SLinus Torvalds err = -ENOMEM; 470*1da177e4SLinus Torvalds break; 471*1da177e4SLinus Torvalds } 472*1da177e4SLinus Torvalds 473*1da177e4SLinus Torvalds if ((err = register_netdev(dev))) { 474*1da177e4SLinus Torvalds free_netdev(dev); 475*1da177e4SLinus Torvalds break; 476*1da177e4SLinus Torvalds } 477*1da177e4SLinus Torvalds 478*1da177e4SLinus Torvalds master = dev->priv; 479*1da177e4SLinus Torvalds 480*1da177e4SLinus Torvalds strlcpy(master->qops.id, dev->name, IFNAMSIZ); 481*1da177e4SLinus Torvalds err = register_qdisc(&master->qops); 482*1da177e4SLinus Torvalds 483*1da177e4SLinus Torvalds if (err) { 484*1da177e4SLinus Torvalds unregister_netdev(dev); 485*1da177e4SLinus Torvalds free_netdev(dev); 486*1da177e4SLinus Torvalds break; 487*1da177e4SLinus Torvalds } 488*1da177e4SLinus Torvalds 489*1da177e4SLinus Torvalds list_add_tail(&master->master_list, &master_dev_list); 490*1da177e4SLinus Torvalds } 491*1da177e4SLinus Torvalds return i ? 0 : err; 492*1da177e4SLinus Torvalds } 493*1da177e4SLinus Torvalds 494*1da177e4SLinus Torvalds static void __exit teql_exit(void) 495*1da177e4SLinus Torvalds { 496*1da177e4SLinus Torvalds struct teql_master *master, *nxt; 497*1da177e4SLinus Torvalds 498*1da177e4SLinus Torvalds list_for_each_entry_safe(master, nxt, &master_dev_list, master_list) { 499*1da177e4SLinus Torvalds 500*1da177e4SLinus Torvalds list_del(&master->master_list); 501*1da177e4SLinus Torvalds 502*1da177e4SLinus Torvalds unregister_qdisc(&master->qops); 503*1da177e4SLinus Torvalds unregister_netdev(master->dev); 504*1da177e4SLinus Torvalds free_netdev(master->dev); 505*1da177e4SLinus Torvalds } 506*1da177e4SLinus Torvalds } 507*1da177e4SLinus Torvalds 508*1da177e4SLinus Torvalds module_init(teql_init); 509*1da177e4SLinus Torvalds module_exit(teql_exit); 510*1da177e4SLinus Torvalds 511*1da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 512