📄 lec.c
字号:
atomic_add(skb->truesize, &send_vcc->tx_inuse); priv->stats.tx_packets++; priv->stats.tx_bytes += skb->len; send_vcc->send(send_vcc, skb); } else { priv->stats.tx_dropped++; dev_kfree_skb(skb); }#if 0 /* Should we wait for card's device driver to notify us? */ dev->tbusy=0;#endif return 0;}/* The inverse routine to net_open(). */static int lec_close(struct net_device *dev) { netif_stop_queue(dev); return 0;}/* * Get the current statistics. * This may be called with the card open or closed. */static struct net_device_stats *lec_get_stats(struct net_device *dev){ return &((struct lec_priv *)dev->priv)->stats;}static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb){ struct net_device *dev = (struct net_device*)vcc->proto_data; struct lec_priv *priv = (struct lec_priv*)dev->priv; struct atmlec_msg *mesg; struct lec_arp_table *entry; int i; char *tmp; /* FIXME */ atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse); mesg = (struct atmlec_msg *)skb->data; tmp = skb->data; tmp += sizeof(struct atmlec_msg); DPRINTK("%s: msg from zeppelin:%d\n", dev->name, mesg->type); switch(mesg->type) { case l_set_mac_addr: for (i=0;i<6;i++) { dev->dev_addr[i] = mesg->content.normal.mac_addr[i]; } break; case l_del_mac_addr: for(i=0;i<6;i++) { dev->dev_addr[i] = 0; } break; case l_addr_delete: lec_addr_delete(priv, mesg->content.normal.atm_addr, mesg->content.normal.flag); break; case l_topology_change: priv->topology_change = mesg->content.normal.flag; break; case l_flush_complete: lec_flush_complete(priv, mesg->content.normal.flag); break; case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */ entry = lec_arp_find(priv, mesg->content.normal.mac_addr); lec_arp_remove(priv->lec_arp_tables, entry); if (mesg->content.normal.no_source_le_narp) break; /* FALL THROUGH */ case l_arp_update: lec_arp_update(priv, mesg->content.normal.mac_addr, mesg->content.normal.atm_addr, mesg->content.normal.flag, mesg->content.normal.targetless_le_arp); DPRINTK("lec: in l_arp_update\n"); if (mesg->sizeoftlvs != 0) { /* LANE2 3.1.5 */ DPRINTK("lec: LANE2 3.1.5, got tlvs, size %d\n", mesg->sizeoftlvs); lane2_associate_ind(dev, mesg->content.normal.mac_addr, tmp, mesg->sizeoftlvs); } break; case l_config: priv->maximum_unknown_frame_count = mesg->content.config.maximum_unknown_frame_count; priv->max_unknown_frame_time = (mesg->content.config.max_unknown_frame_time*HZ); priv->max_retry_count = mesg->content.config.max_retry_count; priv->aging_time = (mesg->content.config.aging_time*HZ); priv->forward_delay_time = (mesg->content.config.forward_delay_time*HZ); priv->arp_response_time = (mesg->content.config.arp_response_time*HZ); priv->flush_timeout = (mesg->content.config.flush_timeout*HZ); priv->path_switching_delay = (mesg->content.config.path_switching_delay*HZ); priv->lane_version = mesg->content.config.lane_version; /* LANE2 */ priv->lane2_ops = NULL; if (priv->lane_version > 1) priv->lane2_ops = &lane2_ops; if (dev->change_mtu(dev, mesg->content.config.mtu)) printk("%s: change_mtu to %d failed\n", dev->name, mesg->content.config.mtu); priv->is_proxy = mesg->content.config.is_proxy; break; case l_flush_tran_id: lec_set_flush_tran_id(priv, mesg->content.normal.atm_addr, mesg->content.normal.flag); break; case l_set_lecid: priv->lecid=(unsigned short)(0xffff&mesg->content.normal.flag); break; case l_should_bridge: {#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) struct net_bridge_fdb_entry *f; DPRINTK("%s: bridge zeppelin asks about 0x%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, mesg->content.proxy.mac_addr[0], mesg->content.proxy.mac_addr[1], mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3], mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]); if (br_fdb_get_hook == NULL || dev->br_port == NULL) break; f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr); if (f != NULL && f->dst->dev != dev && f->dst->state == BR_STATE_FORWARDING) { /* hit from bridge table, send LE_ARP_RESPONSE */ struct sk_buff *skb2; DPRINTK("%s: entry found, responding to zeppelin\n", dev->name); skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); if (skb2 == NULL) { br_fdb_put_hook(f); break; } skb2->len = sizeof(struct atmlec_msg); memcpy(skb2->data, mesg, sizeof(struct atmlec_msg)); atm_force_charge(priv->lecd, skb2->truesize); skb_queue_tail(&priv->lecd->recvq, skb2); wake_up(&priv->lecd->sleep); } if (f != NULL) br_fdb_put_hook(f);#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ } break; default: printk("%s: Unknown message type %d\n", dev->name, mesg->type); dev_kfree_skb(skb); return -EINVAL; } dev_kfree_skb(skb); return 0;}static void lec_atm_close(struct atm_vcc *vcc){ struct sk_buff *skb; struct net_device *dev = (struct net_device *)vcc->proto_data; struct lec_priv *priv = (struct lec_priv *)dev->priv; priv->lecd = NULL; /* Do something needful? */ netif_stop_queue(dev); lec_arp_destroy(priv); if (skb_peek(&vcc->recvq)) printk("%s lec_atm_close: closing with messages pending\n", dev->name); while ((skb = skb_dequeue(&vcc->recvq))) { atm_return(vcc, skb->truesize); dev_kfree_skb(skb); } printk("%s: Shut down!\n", dev->name); MOD_DEC_USE_COUNT;}static struct atmdev_ops lecdev_ops = { close: lec_atm_close, send: lec_atm_send};static struct atm_dev lecatm_dev = { &lecdev_ops, NULL, /*PHY*/ "lec", /*type*/ 999, /*dummy device number*/ NULL,NULL, /*no VCCs*/ NULL,NULL, /*no data*/ { 0 }, /*no flags*/ NULL, /* no local address*/ { 0 } /*no ESI or rest of the atm_dev struct things*/};/* * LANE2: new argument struct sk_buff *data contains * the LE_ARP based TLVs introduced in the LANE2 spec */int send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, unsigned char *mac_addr, unsigned char *atm_addr, struct sk_buff *data){ struct sk_buff *skb; struct atmlec_msg *mesg; if (!priv || !priv->lecd) { return -1; } skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); if (!skb) return -1; skb->len = sizeof(struct atmlec_msg); mesg = (struct atmlec_msg *)skb->data; memset(mesg, 0, sizeof(struct atmlec_msg)); mesg->type = type; if (data != NULL) mesg->sizeoftlvs = data->len; if (mac_addr) memcpy(&mesg->content.normal.mac_addr, mac_addr, ETH_ALEN); else mesg->content.normal.targetless_le_arp = 1; if (atm_addr) memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); atm_force_charge(priv->lecd, skb->truesize); skb_queue_tail(&priv->lecd->recvq, skb); wake_up(&priv->lecd->sleep); if (data != NULL) { DPRINTK("lec: about to send %d bytes of data\n", data->len); atm_force_charge(priv->lecd, data->truesize); skb_queue_tail(&priv->lecd->recvq, data); wake_up(&priv->lecd->sleep); } return 0;}/* shamelessly stolen from drivers/net/net_init.c */static int lec_change_mtu(struct net_device *dev, int new_mtu){ if ((new_mtu < 68) || (new_mtu > 18190)) return -EINVAL; dev->mtu = new_mtu; return 0;}static void lec_init(struct net_device *dev){ dev->change_mtu = lec_change_mtu; dev->open = lec_open; dev->stop = lec_close; dev->hard_start_xmit = lec_send_packet; dev->get_stats = lec_get_stats; dev->set_multicast_list = NULL; dev->do_ioctl = NULL; printk("%s: Initialized!\n",dev->name); return;}static unsigned char lec_ctrl_magic[] = { 0xff, 0x00, 0x01, 0x01 };void lec_push(struct atm_vcc *vcc, struct sk_buff *skb){ struct net_device *dev = (struct net_device *)vcc->proto_data; struct lec_priv *priv = (struct lec_priv *)dev->priv; #if DUMP_PACKETS >0 int i=0; char buf[300]; printk("%s: lec_push vcc vpi:%d vci:%d\n", dev->name, vcc->vpi, vcc->vci);#endif if (!skb) { DPRINTK("%s: null skb\n",dev->name); lec_vcc_close(priv, vcc); return; }#if DUMP_PACKETS > 0 printk("%s: rcv datalen:%ld lecid:%4.4x\n", dev->name, skb->len, priv->lecid);#if DUMP_PACKETS >= 2 for(i=0;i<skb->len && i <99;i++) { sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]); }#elif DUMP_PACKETS >= 1 for(i=0;i<skb->len && i < 30;i++) { sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]); }#endif /* DUMP_PACKETS >= 1 */ if (i==skb->len) printk("%s\n",buf); else printk("%s...\n",buf);#endif /* DUMP_PACKETS > 0 */ if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/ DPRINTK("%s: To daemon\n",dev->name); skb_queue_tail(&vcc->recvq, skb); wake_up(&vcc->sleep); } else { /* Data frame, queue to protocol handlers */ unsigned char *dst; atm_return(vcc,skb->truesize); if (*(uint16_t *)skb->data == htons(priv->lecid) || !priv->lecd) { /* Probably looping back, or if lecd is missing, lecd has gone down */ DPRINTK("Ignoring loopback frame...\n"); dev_kfree_skb(skb); return; }#ifdef CONFIG_TR if (priv->is_trdev) dst = ((struct lecdatahdr_8025 *)skb->data)->h_dest; else#endif dst = ((struct lecdatahdr_8023 *)skb->data)->h_dest; if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */ !priv->is_proxy && /* Proxy wants all the packets */ memcmp(dst, dev->dev_addr, dev->addr_len)) { dev_kfree_skb(skb); return; } if (priv->lec_arp_empty_ones) { lec_arp_check_empties(priv, vcc, skb); } skb->dev = dev; skb->data += 2; /* skip lec_id */#ifdef CONFIG_TR if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev); else#endif skb->protocol = eth_type_trans(skb, dev); priv->stats.rx_packets++; priv->stats.rx_bytes += skb->len; netif_rx(skb); }}int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -