int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg) { struct mpoa_client *mpc; struct lec_priv *priv; if (mpcs == NULL) { init_timer(&mpc_timer); mpc_timer_refresh(); /* This lets us now how our LECs are doing */ register_netdevice_notifier(&mpoa_notifier); } mpc = find_mpc_by_itfnum(arg); if (mpc == NULL) { dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg); mpc = alloc_mpc(); if (mpc == NULL) return -ENOMEM; mpc->dev_num = arg; mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */ } if (mpc->mpoad_vcc) { printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg); return -EADDRINUSE; } if (mpc->dev) { /* check if the lec is LANE2 capable */ priv = (struct lec_priv *)mpc->dev->priv; if (priv->lane_version < 2) { dev_put(mpc->dev); mpc->dev = NULL; } else priv->lane2_ops->associate_indicator = lane2_assoc_ind; } mpc->mpoad_vcc = vcc; vcc->dev = &mpc_dev; vcc_insert_socket(vcc->sk); set_bit(ATM_VF_META,&vcc->flags); set_bit(ATM_VF_READY,&vcc->flags); if (mpc->dev) { char empty[ATM_ESA_LEN]; memset(empty, 0, ATM_ESA_LEN); start_mpc(mpc, mpc->dev); /* set address if mpcd e.g. gets killed and restarted. * If we do not do it now we have to wait for the next LE_ARP */ if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 ) send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc); } __module_get(THIS_MODULE); return arg; }
static int atm_mpoa_vcc_attach(struct atm_vcc *vcc, void __user *arg) { int bytes_left; struct mpoa_client *mpc; struct atmmpc_ioc ioc_data; in_cache_entry *in_entry; __be32 ipaddr; bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmmpc_ioc)); if (bytes_left != 0) { pr_info("mpoa:Short read (missed %d bytes) from userland\n", bytes_left); return -EFAULT; } ipaddr = ioc_data.ipaddr; if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF) return -EINVAL; mpc = find_mpc_by_itfnum(ioc_data.dev_num); if (mpc == NULL) return -EINVAL; if (ioc_data.type == MPC_SOCKET_INGRESS) { in_entry = mpc->in_ops->get(ipaddr, mpc); if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) { pr_info("(%s) did not find RESOLVED entry from ingress cache\n", mpc->dev->name); if (in_entry != NULL) mpc->in_ops->put(in_entry); return -EINVAL; } pr_info("(%s) attaching ingress SVC, entry = %pI4\n", mpc->dev->name, &in_entry->ctrl_info.in_dst_ip); in_entry->shortcut = vcc; mpc->in_ops->put(in_entry); } else { pr_info("(%s) attaching egress SVC\n", mpc->dev->name); } vcc->proto_data = mpc->dev; vcc->push = mpc_push; return 0; }
int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg) { int bytes_left; struct mpoa_client *mpc; struct atmmpc_ioc ioc_data; in_cache_entry *in_entry; uint32_t ipaddr; unsigned char *ip; bytes_left = copy_from_user(&ioc_data, (void *)arg, sizeof(struct atmmpc_ioc)); if (bytes_left != 0) { printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left); return -EFAULT; } ipaddr = ioc_data.ipaddr; if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF) return -EINVAL; mpc = find_mpc_by_itfnum(ioc_data.dev_num); if (mpc == NULL) return -EINVAL; if (ioc_data.type == MPC_SOCKET_INGRESS) { in_entry = mpc->in_ops->get(ipaddr, mpc); if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) { printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n", mpc->dev->name); if (in_entry != NULL) mpc->in_ops->put(in_entry); return -EINVAL; } ip = (unsigned char*)&in_entry->ctrl_info.in_dst_ip; printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n", mpc->dev->name, ip[0], ip[1], ip[2], ip[3]); in_entry->shortcut = vcc; mpc->in_ops->put(in_entry); } else { printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name); } vcc->proto_data = mpc->dev; vcc->push = mpc_push; return 0; }
static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *dev_ptr) { struct net_device *dev; struct mpoa_client *mpc; struct lec_priv *priv; dev = (struct net_device *)dev_ptr; if (dev->name == NULL || strncmp(dev->name, "lec", 3)) return NOTIFY_DONE; /* we are only interested in lec:s */ switch (event) { case NETDEV_REGISTER: /* a new lec device was allocated */ priv = (struct lec_priv *)dev->priv; if (priv->lane_version < 2) break; priv->lane2_ops->associate_indicator = lane2_assoc_ind; mpc = find_mpc_by_itfnum(priv->itfnum); if (mpc == NULL) { dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n", dev->name); mpc = alloc_mpc(); if (mpc == NULL) { printk("mpoa: mpoa_event_listener: no new mpc"); break; } } mpc->dev_num = priv->itfnum; mpc->dev = dev; dev_hold(dev); dprintk("mpoa: (%s) was initialized\n", dev->name); break; case NETDEV_UNREGISTER: /* the lec device was deallocated */ mpc = find_mpc_by_lec(dev); if (mpc == NULL) break; dprintk("mpoa: device (%s) was deallocated\n", dev->name); stop_mpc(mpc); dev_put(mpc->dev); mpc->dev = NULL; break; case NETDEV_UP: /* the dev was ifconfig'ed up */ mpc = find_mpc_by_lec(dev); if (mpc == NULL) break; if (mpc->mpoad_vcc != NULL) { start_mpc(mpc, dev); } break; case NETDEV_DOWN: /* the dev was ifconfig'ed down */ /* this means that the flow of packets from the * upper layer stops */ mpc = find_mpc_by_lec(dev); if (mpc == NULL) break; if (mpc->mpoad_vcc != NULL) { stop_mpc(mpc); } break; case NETDEV_REBOOT: case NETDEV_CHANGE: case NETDEV_CHANGEMTU: case NETDEV_CHANGEADDR: case NETDEV_GOING_DOWN: break; default: break; } return NOTIFY_DONE; }