Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}