📄 arcnet.c
字号:
break;#endif case ARC_P_DATAPOINT_BOOT: case ARC_P_DATAPOINT_MOUNT: break; case ARC_P_POWERLAN_BEACON: case ARC_P_POWERLAN_BEACON2: break; case ARC_P_LANSOFT: /* don't understand. fall through. */ default: BUGMSG(D_EXTRA,"received unknown protocol %d (%Xh) from station %d.\n", arcsoft[0],arcsoft[0],saddr); lp->stats.rx_errors++; lp->stats.rx_crc_errors++; break; } /* If any worth-while packets have been received, a mark_bh(NET_BH) * has been done by netif_rx and Linux will handle them after we * return. */}/* Packet receiver for "standard" RFC1201-style packets */static voidarcnetA_rx(struct device *dev,u_char *buf, int length, u_char saddr, u_char daddr){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; struct sk_buff *skb; struct ClientData *arcsoft,*soft; BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n", length); /* compensate for EXTRA_CLIENTDATA (which isn't actually in the * packet) */ arcsoft=(struct ClientData *)(buf-EXTRA_CLIENTDATA); length+=EXTRA_CLIENTDATA; if (arcsoft->split_flag==0xFF) /* Exception Packet */ { BUGMSG(D_DURING,"compensating for exception packet\n"); /* skip over 4-byte junkola */ arcsoft=(struct ClientData *) ((u_char *)arcsoft + 4); length-=4; } if (!arcsoft->split_flag) /* not split */ { struct Incoming *in=&lp->incoming[saddr]; BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n", arcsoft->split_flag); if (in->skb) /* already assembling one! */ { BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n", in->sequence,arcsoft->split_flag, arcsoft->sequence); lp->aborted_seq=arcsoft->sequence; kfree_skb(in->skb); lp->stats.rx_errors++; lp->stats.rx_missed_errors++; in->skb=NULL; } in->sequence=arcsoft->sequence; skb = alloc_skb(length, GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n"); lp->stats.rx_dropped++; return; } soft=(struct ClientData *)skb->data; skb_put(skb,length); skb->dev = dev; memcpy((u_char *)soft+EXTRA_CLIENTDATA, (u_char *)arcsoft+EXTRA_CLIENTDATA, length-EXTRA_CLIENTDATA); soft->daddr=daddr; soft->saddr=saddr; /* ARP packets have problems when sent from DOS. * source address is always 0 on some systems! So we take * the hardware source addr (which is impossible to fumble) * and insert it ourselves. */ if (soft->protocol_id == ARC_P_ARP) { struct arphdr *arp=(struct arphdr *) ((char *)soft+sizeof(struct ClientData)); /* make sure addresses are the right length */ if (arp->ar_hln==1 && arp->ar_pln==4) { char *cptr=(char *)(arp)+sizeof(struct arphdr); if (!*cptr) /* is saddr = 00? */ { BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n", saddr); lp->stats.rx_crc_errors++; *cptr=saddr; } else { BUGMSG(D_DURING,"ARP source address (%Xh) is fine.\n", *cptr); } } else { BUGMSG(D_NORMAL,"funny-shaped ARP packet. (%Xh, %Xh)\n", arp->ar_hln,arp->ar_pln); lp->stats.rx_errors++; lp->stats.rx_crc_errors++; } } BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); lp->stats.rx_bytes += skb->len; skb->protocol=arcnetA_type_trans(skb,dev); netif_rx(skb); } else /* split packet */ { /* NOTE: MSDOS ARP packet correction should only need to * apply to unsplit packets, since ARP packets are so short. * * My interpretation of the RFC1201 (ARCnet) document is that * if a packet is received out of order, the entire assembly * process should be aborted. * * The RFC also mentions "it is possible for successfully * received packets to be retransmitted." As of 0.40 all * previously received packets are allowed, not just the * most recent one. * * We allow multiple assembly processes, one for each * ARCnet card possible on the network. Seems rather like * a waste of memory. Necessary? */ struct Incoming *in=&lp->incoming[saddr]; BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n", arcsoft->split_flag,in->sequence); if (in->skb && in->sequence!=arcsoft->sequence) { BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n", saddr,in->sequence,arcsoft->sequence, arcsoft->split_flag); kfree_skb(in->skb); in->skb=NULL; lp->stats.rx_errors++; lp->stats.rx_missed_errors++; in->lastpacket=in->numpackets=0; } if (arcsoft->split_flag & 1) /* first packet in split */ { BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n", arcsoft->split_flag); if (in->skb) /* already assembling one! */ { BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n", in->sequence,arcsoft->split_flag, arcsoft->sequence); lp->stats.rx_errors++; lp->stats.rx_missed_errors++; kfree_skb(in->skb); } in->sequence=arcsoft->sequence; in->numpackets=((unsigned)arcsoft->split_flag>>1)+2; in->lastpacket=1; if (in->numpackets>16) { BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n", arcsoft->split_flag); lp->stats.rx_errors++; lp->stats.rx_length_errors++; return; } in->skb=skb=alloc_skb(508*in->numpackets + sizeof(struct ClientData), GFP_ATOMIC); if (skb == NULL) { BUGMSG(D_NORMAL,"(split) memory squeeze, dropping packet.\n"); lp->stats.rx_dropped++; return; } soft=(struct ClientData *)skb->data; skb_put(skb,sizeof(struct ClientData)); skb->dev=dev; memcpy((u_char *)soft+EXTRA_CLIENTDATA, (u_char *)arcsoft+EXTRA_CLIENTDATA, sizeof(struct ClientData)-EXTRA_CLIENTDATA); soft->split_flag=0; /* final packet won't be split */ } else /* not first packet */ { int packetnum=((unsigned)arcsoft->split_flag>>1) + 1; /* if we're not assembling, there's no point * trying to continue. */ if (!in->skb) { if (lp->aborted_seq != arcsoft->sequence) { BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n", arcsoft->split_flag,arcsoft->sequence, lp->aborted_seq); lp->stats.rx_errors++; lp->stats.rx_missed_errors++; } return; } in->lastpacket++; if (packetnum!=in->lastpacket) /* not the right flag! */ { /* harmless duplicate? ignore. */ if (packetnum<=in->lastpacket-1) { BUGMSG(D_EXTRA,"duplicate splitpacket ignored! (splitflag=%d)\n", arcsoft->split_flag); lp->stats.rx_errors++; lp->stats.rx_frame_errors++; return; } /* "bad" duplicate, kill reassembly */ BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n", in->sequence,arcsoft->split_flag, arcsoft->sequence); lp->aborted_seq=arcsoft->sequence; kfree_skb(in->skb); in->skb=NULL; lp->stats.rx_errors++; lp->stats.rx_missed_errors++; in->lastpacket=in->numpackets=0; return; } soft=(struct ClientData *)in->skb->data; } skb=in->skb; memcpy(skb->data+skb->len, (u_char *)arcsoft+sizeof(struct ClientData), length-sizeof(struct ClientData)); skb_put(skb,length-sizeof(struct ClientData)); soft->daddr=daddr; soft->saddr=saddr; /* are we done? */ if (in->lastpacket == in->numpackets) { if (!skb || !in->skb) { BUGMSG(D_NORMAL,"?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n", skb,in->skb); } else { in->skb=NULL; in->lastpacket=in->numpackets=0; BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx"); lp->stats.rx_bytes += skb->len; skb->protocol=arcnetA_type_trans(skb,dev); netif_rx(skb); } } }}/**************************************************************************** * * * Miscellaneous routines * * * ****************************************************************************//* Get the current statistics. This may be called with the card open or * closed. */static struct net_device_stats *arcnet_get_stats(struct device *dev){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; return &lp->stats;}/* Create the ARCnet ClientData header for an arbitrary protocol layer * * saddr=NULL means use device source address (always will anyway) * daddr=NULL means leave destination address (eg unresolved arp) */static int arcnetA_header(struct sk_buff *skb,struct device *dev, unsigned short type,void *daddr,void *saddr,unsigned len){ struct ClientData *head = (struct ClientData *) skb_push(skb,dev->hard_header_len); struct arcnet_local *lp=(struct arcnet_local *)(dev->priv); BUGMSG(D_DURING,"create header from %d to %d; protocol %d (%Xh); size %u.\n", saddr ? *(u_char*)saddr : -1, daddr ? *(u_char*)daddr : -1, type,type,len); /* set the protocol ID according to RFC1201 */ switch(type) { case ETH_P_IP: head->protocol_id=ARC_P_IP; break; case ETH_P_ARP: head->protocol_id=ARC_P_ARP; break; case ETH_P_RARP: head->protocol_id=ARC_P_RARP; break; case ETH_P_IPX: case ETH_P_802_3: case ETH_P_802_2: head->protocol_id=ARC_P_IPX; break; case ETH_P_ATALK: head->protocol_id=ARC_P_ATALK; break; default: BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n", type,type); lp->stats.tx_errors++; lp->stats.tx_aborted_errors++; return 0; } /* * Set the source hardware address. * * This is pretty pointless for most purposes, but it can help * in debugging. saddr is stored in the ClientData header and * removed before sending the packet (since ARCnet does not allow * us to change the source address in the actual packet sent) */ if(saddr) head->saddr=((u_char*)saddr)[0]; else head->saddr=((u_char*)(dev->dev_addr))[0]; head->split_flag=0; /* split packets are done elsewhere */ head->sequence=0; /* so are sequence numbers */ /* supposedly if daddr is NULL, we should ignore it... */ if(daddr) { head->daddr=((u_char*)daddr)[0]; return dev->hard_header_len; } else head->daddr=0; /* better fill one in anyway */ return -dev->hard_header_len;}/* Rebuild the ARCnet ClientData header. This is called after an ARP * (or in future other address resolution) has completed on this * sk_buff. We now let ARP fill in the other fields. */static int arcnetA_rebuild_header(struct sk_buff *skb){ struct ClientData *head = (struct ClientData *)skb->data; struct device *dev=skb->dev; struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);#ifdef CONFIG_INET int status;#endif /* * Only ARP and IP are currently supported * * FIXME: Anyone want to spec IPv6 over ARCnet ? */ if(head->protocol_id != ARC_P_IP) { BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n", head->protocol_id,head->protocol_id); lp->stats.tx_errors++; lp->stats.tx_aborted_errors++; head->daddr=0; /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/ return 0; } /* * Try to get ARP to resolve the header. */#ifdef CONFIG_INET BUGMSG(D_DURING,"rebuild header from %d to %d; protocol %Xh\n", head->saddr,head->daddr,head->protocol_id); status=arp_find(&(head->daddr),skb)? 1 : 0; BUGMSG(D_DURING," rebuilt: from %d to %d; protocol %Xh\n", head->saddr,head->daddr,head->protocol_id); return status;#else return 0;#endif}/* Determine a packet's protocol ID. * * With ARCnet we have to convert everything to Ethernet-style stuff. */static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev){ struct ClientData *head; struct arcnet_local *lp=(struct arcnet_local *) (dev->priv); /* Pull off the arcnet header. */ skb->mac.raw=skb->data; skb_pull(skb,dev->hard_header_len); head=(struct ClientData *)skb->mac.raw; if (head->daddr==0) skb->pkt_type=PACKET_BROADCAST; else if (dev->flags&IFF_PROMISC) { /* if we're not sending to ourselves :) */ if (head->daddr != dev->dev_addr[0]) skb->pkt_type=PACKET_OTHERHOST; } /* now return the protocol number */ switch (head->protocol_id) { case ARC_P_IP: return htons(ETH_P_IP); case ARC_P_ARP: return htons(ETH_P_ARP); case ARC_P_RARP: return htons(ETH_P_RARP); case ARC_P_IPX: case ARC_P_NOVELL_EC: return htons(ETH_P_802_3); default: lp->stats.rx_errors++; lp->stats.rx_crc_errors++; return 0; } return htons(ETH_P_IP);}#ifdef CONFIG_ARCNET_ETH/**************************************************************************** * * * Ethernet-Encap Support * * * ****************************************************************************//* Initialize the arc0e device. */static int arcnetE_init(struct device *dev){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; ether_setup(dev); /* we're emulating ether here, not ARCnet */ dev->dev_addr[0]=0; dev->dev_addr[5]=lp->stationid; dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len-1; dev->open=arcnetE_open_close; dev->stop=arcnetE_open_close; dev->hard_start_xmit=arcnetE_send_packet; return 0;}/* Bring up/down the arc0e device - we don't actually have to do anything, * since our parent arc0 handles the card I/O itself. */static int arcnetE_open_close(struct device *dev){ return 0;}/* Called by the kernel in order to transmit an ethernet-type packet. */static intarcnetE_send_packet(struct sk_buff *skb, struct device *dev){ struct arcnet_local *lp = (struct arcnet_local *)dev->priv; int bad,oldmask=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -