⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rfc1201.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
			}			in->sequence = soft->sequence;			in->numpackets = ((unsigned) soft->split_flag >> 1) + 2;			in->lastpacket = 1;			if (in->numpackets > 16) {				BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n",				       soft->split_flag);				lp->rfc1201.aborted_seq = soft->sequence;				lp->stats.rx_errors++;				lp->stats.rx_length_errors++;				return;			}			in->skb = skb = alloc_skb(508 * in->numpackets + ARC_HDR_SIZE,						  GFP_ATOMIC);			if (skb == NULL) {				BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n");				lp->rfc1201.aborted_seq = soft->sequence;				lp->stats.rx_dropped++;				return;			}			skb->dev = dev;			pkt = (struct archdr *) skb->data;			soft = &pkt->soft.rfc1201;			memcpy(pkt, pkthdr, ARC_HDR_SIZE + RFC1201_HDR_SIZE);			skb_put(skb, ARC_HDR_SIZE + RFC1201_HDR_SIZE);			soft->split_flag = 0;	/* end result won't be split */		} else {	/* not first packet */			int packetnum = ((unsigned) soft->split_flag >> 1) + 1;			/*			 * if we're not assembling, there's no point trying to			 * continue.			 */			if (!in->skb) {				if (lp->rfc1201.aborted_seq != soft->sequence) {					BUGMSG(D_EXTRA, "can't continue split without starting "					       "first! (splitflag=%d, seq=%d, aborted=%d)\n",					soft->split_flag, soft->sequence,					       lp->rfc1201.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",					       soft->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, soft->split_flag, soft->sequence);				lp->rfc1201.aborted_seq = soft->sequence;				dev_kfree_skb_irq(in->skb);				in->skb = NULL;				lp->stats.rx_errors++;				lp->stats.rx_missed_errors++;				in->lastpacket = in->numpackets = 0;				return;			}			pkt = (struct archdr *) in->skb->data;			soft = &pkt->soft.rfc1201;		}		skb = in->skb;		lp->hw.copy_from_card(dev, bufnum, ofs + RFC1201_HDR_SIZE,				      skb->data + skb->len,				      length - RFC1201_HDR_SIZE);		skb_put(skb, length - RFC1201_HDR_SIZE);		/* are we done? */		if (in->lastpacket == in->numpackets) {			in->skb = NULL;			in->lastpacket = in->numpackets = 0;	    BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (unsplit)\n",    		skb->len, pkt->hard.source);	    BUGMSG(D_SKB_SIZE, "skb: received %d bytes from %02X (split)\n",    		skb->len, pkt->hard.source);			BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");			skb->protocol = type_trans(skb, dev);			netif_rx(skb);			dev->last_rx = jiffies;		}	}}/* Create the ARCnet hard/soft headers for RFC1201. */static int build_header(struct sk_buff *skb, struct net_device *dev,			unsigned short type, uint8_t daddr){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;	struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);	struct arc_rfc1201 *soft = &pkt->soft.rfc1201;	/* set the protocol ID according to RFC1201 */	switch (type) {	case ETH_P_IP:		soft->proto = ARC_P_IP;		break;	case ETH_P_IPV6:		soft->proto = ARC_P_IPV6;		break;	case ETH_P_ARP:		soft->proto = ARC_P_ARP;		break;	case ETH_P_RARP:		soft->proto = ARC_P_RARP;		break;	case ETH_P_IPX:	case ETH_P_802_3:	case ETH_P_802_2:		soft->proto = ARC_P_IPX;		break;	case ETH_P_ATALK:		soft->proto = ARC_P_ATALK;		break;	default:		BUGMSG(D_NORMAL, "RFC1201: 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.  ARCnet does not allow us to change the source address in	 * the actual packet sent)	 */	pkt->hard.source = *dev->dev_addr;	soft->sequence = htons(lp->rfc1201.sequence++);	soft->split_flag = 0;	/* split packets are done elsewhere */	/* see linux/net/ethernet/eth.c to see where I got the following */	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {		/* 		 * FIXME: fill in the last byte of the dest ipaddr here to better		 * comply with RFC1051 in "noarp" mode.  For now, always broadcasting		 * will probably at least get packets sent out :)		 */		pkt->hard.dest = 0;		return hdr_size;	}	/* otherwise, drop in the dest address */	pkt->hard.dest = daddr;	return hdr_size;}static void load_pkt(struct net_device *dev, struct arc_hardware *hard,		     struct arc_rfc1201 *soft, int softlen, int bufnum){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	int ofs;	/* assume length <= XMTU: someone should have handled that by now. */	if (softlen > MinTU) {		hard->offset[0] = 0;		hard->offset[1] = ofs = 512 - softlen;	} else if (softlen > MTU) {	/* exception packet - add an extra header */		struct arc_rfc1201 excsoft;		excsoft.proto = soft->proto;		excsoft.split_flag = 0xff;		excsoft.sequence = 0xffff;		hard->offset[0] = 0;		ofs = 512 - softlen;		hard->offset[1] = ofs - RFC1201_HDR_SIZE;		lp->hw.copy_to_card(dev, bufnum, ofs - RFC1201_HDR_SIZE,				    &excsoft, RFC1201_HDR_SIZE);	} else		hard->offset[0] = ofs = 256 - softlen;	lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE);	lp->hw.copy_to_card(dev, bufnum, ofs, soft, softlen);	lp->lastload_dest = hard->dest;}static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,		      int bufnum){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	const int maxsegsize = XMTU - RFC1201_HDR_SIZE;	struct Outgoing *out;	BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n",	       lp->next_tx, lp->cur_tx, bufnum);	length -= ARC_HDR_SIZE;	/* hard header is not included in packet length */	pkt->soft.rfc1201.split_flag = 0;	/* need to do a split packet? */	if (length > XMTU) {		out = &lp->outgoing;		out->length = length - RFC1201_HDR_SIZE;		out->dataleft = lp->outgoing.length;		out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize;		out->segnum = 0;		BUGMSG(D_DURING, "rfc1201 prep_tx: ready for %d-segment split "		       "(%d bytes, seq=%d)\n", out->numsegs, out->length,		       pkt->soft.rfc1201.sequence);		return 0;	/* not done */	}	/* just load the packet into the buffers and send it off */	load_pkt(dev, &pkt->hard, &pkt->soft.rfc1201, length, bufnum);	return 1;		/* done */}static int continue_tx(struct net_device *dev, int bufnum){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	struct Outgoing *out = &lp->outgoing;	struct arc_hardware *hard = &out->pkt->hard;	struct arc_rfc1201 *soft = &out->pkt->soft.rfc1201, *newsoft;	int maxsegsize = XMTU - RFC1201_HDR_SIZE;	int seglen;	BUGMSG(D_DURING,	  "rfc1201 continue_tx: loading segment %d(+1) of %d (seq=%d)\n",	       out->segnum, out->numsegs, soft->sequence);	/* the "new" soft header comes right before the data chunk */	newsoft = (struct arc_rfc1201 *)	    (out->pkt->soft.raw + out->length - out->dataleft);	if (!out->segnum)	/* first packet; newsoft == soft */		newsoft->split_flag = ((out->numsegs - 2) << 1) | 1;	else {		newsoft->split_flag = out->segnum << 1;		newsoft->proto = soft->proto;		newsoft->sequence = soft->sequence;	}	seglen = maxsegsize;	if (seglen > out->dataleft)		seglen = out->dataleft;	out->dataleft -= seglen;	load_pkt(dev, hard, newsoft, seglen + RFC1201_HDR_SIZE, bufnum);	out->segnum++;	if (out->segnum >= out->numsegs)		return 1;	else		return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -