static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb) { struct mpoa_client *mpc = find_mpc_by_vcc(vcc); struct k_message *mesg = (struct k_message *)skb->data; atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); if (mpc == NULL) { pr_info("no mpc found\n"); return 0; } dprintk("(%s)", mpc->dev ? mpc->dev->name : "<unknown>"); switch (mesg->type) { case MPOA_RES_REPLY_RCVD: dprintk_cont("mpoa_res_reply_rcvd\n"); MPOA_res_reply_rcvd(mesg, mpc); break; case MPOA_TRIGGER_RCVD: dprintk_cont("mpoa_trigger_rcvd\n"); MPOA_trigger_rcvd(mesg, mpc); break; case INGRESS_PURGE_RCVD: dprintk_cont("nhrp_purge_rcvd\n"); ingress_purge_rcvd(mesg, mpc); break; case EGRESS_PURGE_RCVD: dprintk_cont("egress_purge_reply_rcvd\n"); egress_purge_rcvd(mesg, mpc); break; case MPS_DEATH: dprintk_cont("mps_death\n"); mps_death(mesg, mpc); break; case CACHE_IMPOS_RCVD: dprintk_cont("cache_impos_rcvd\n"); MPOA_cache_impos_rcvd(mesg, mpc); break; case SET_MPC_CTRL_ADDR: dprintk_cont("set_mpc_ctrl_addr\n"); set_mpc_ctrl_addr_rcvd(mesg, mpc); break; case SET_MPS_MAC_ADDR: dprintk_cont("set_mps_mac_addr\n"); set_mps_mac_addr_rcvd(mesg, mpc); break; case CLEAN_UP_AND_EXIT: dprintk_cont("clean_up_and_exit\n"); clean_up(mesg, mpc, DIE); break; case RELOAD: dprintk_cont("reload\n"); clean_up(mesg, mpc, RELOAD); break; case SET_MPC_PA
static void stop_mpc(struct mpoa_client *mpc) { struct net_device *dev = mpc->dev; dprintk("(%s)", mpc->dev->name); /* Lets not nullify lec device's dev->hard_start_xmit */ if (dev->netdev_ops != &mpc->new_ops) { dprintk_cont(" mpc already stopped, not fatal\n"); return; } dprintk_cont("\n"); dev->netdev_ops = mpc->old_ops; mpc->old_ops = NULL; /* close_shortcuts(mpc); ??? FIXME */ }
static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc) { struct lec_priv *priv; int i, retval ; uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN]; tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type */ tlv[4] = 1 + 1 + ATM_ESA_LEN; /* length */ tlv[5] = 0x02; /* MPOA client */ tlv[6] = 0x00; /* number of MPS MAC addresses */ memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */ memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN); dprintk("(%s) setting MPC ctrl ATM address to", mpc->dev ? mpc->dev->name : "<unknown>"); for (i = 7; i < sizeof(tlv); i++) dprintk_cont(" %02x", tlv[i]); dprintk_cont("\n"); if (mpc->dev) { priv = netdev_priv(mpc->dev); retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv)); if (retval == 0) pr_info("(%s) MPOA device type TLV association failed\n", mpc->dev->name); retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL); if (retval < 0) pr_info("(%s) targetless LE_ARP request failed\n", mpc->dev->name); } return; }
/* * lec device calls this via its netdev_priv(dev)->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, const u8 *mac_addr, const u8 *tlvs, u32 sizeoftlvs) { uint32_t type; uint8_t length, mpoa_device_type, number_of_mps_macs; const uint8_t *end_of_tlvs; struct mpoa_client *mpc; mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */ dprintk("(%s) 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) { pr_info("(%s) 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) { pr_info("TLV value extends past its buffer, aborting parse\n"); return; } if (type == 0) { pr_info("mpoa: (%s) 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("(%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)) { /* :) */ pr_info("(%s) 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) { pr_info("(%s) 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 "); 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) { pr_info("(%s) MPS_AND_MPC has zero MACs\n", dev->name); continue; /* someone should read the spec */ } dprintk_cont("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) pr_info("(%s) ignoring %Zd bytes of trailing TLV garbage\n", dev->name, end_of_tlvs - tlvs); return; }