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
/*
 * lec device calls this via its dev->priv->lane2_ops->associate_indicator()
 * when it sees a TLV in LE_ARP packet.
 * We fill in the pointer above when we see a LANE2 lec initializing
 * See LANE2 spec 3.1.5
 *
 * Quite a big and ugly function but when you look at it
 * all it does is to try to locate and parse MPOA Device
 * Type TLV.
 * We give our lec a pointer to this function and when the
 * lec sees a TLV it uses the pointer to call this function.
 *
 */
static void lane2_assoc_ind(struct net_device *dev, uint8_t *mac_addr,
			    uint8_t *tlvs, uint32_t sizeoftlvs)
{
	uint32_t type;
	uint8_t length, mpoa_device_type, number_of_mps_macs;
	uint8_t *end_of_tlvs;
	struct mpoa_client *mpc;
	
	mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
	dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name);
	dprintk("total length of all TLVs %d\n", sizeoftlvs);
	mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */
	if (mpc == NULL) {
		printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name);
		return;
	}
	end_of_tlvs = tlvs + sizeoftlvs;
	while (end_of_tlvs - tlvs >= 5) {
		type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3];
		length = tlvs[4];
		tlvs += 5;
		dprintk("    type 0x%x length %02x\n", type, length);
		if (tlvs + length > end_of_tlvs) {
			printk("TLV value extends past its buffer, aborting parse\n");
			return;
		}
		
		if (type == 0) {
			printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name);
			return;
		}

		if (type != TLV_MPOA_DEVICE_TYPE) {
			tlvs += length;
			continue;  /* skip other TLVs */
		}
		mpoa_device_type = *tlvs++;
		number_of_mps_macs = *tlvs++;
		dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type));
		if (mpoa_device_type == MPS_AND_MPC &&
		    length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
			printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
			       dev->name);
			continue;
		}
		if ((mpoa_device_type == MPS || mpoa_device_type == MPC)
		    && length < 22 + number_of_mps_macs*ETH_ALEN) {
			printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
				dev->name);
			continue;
		}
		if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) {
			dprintk("ignoring non-MPS device\n");
			if (mpoa_device_type == MPC) tlvs += 20;
			continue;  /* we are only interested in MPSs */
		}
		if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) {
			printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name);
			continue;  /* someone should read the spec */
		}
		dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs);
		
		/* ok, now we can go and tell our daemon the control address of MPS */
		send_set_mps_ctrl_addr(tlvs, mpc);
		
		tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type);
		if (tlvs == NULL) return;
	}
	if (end_of_tlvs - tlvs != 0)
		printk("mpoa: (%s) lane2_assoc_ind: ignoring %Zd bytes of trailing TLV carbage\n",
		       dev->name, end_of_tlvs - tlvs);
	return;
}