dvb_net.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,224 行 · 第 1/3 页

C
1,224
字号
				ethh = (struct ethhdr *)skb_put( priv->ule_skb, ETH_HLEN );				memset( ethh->h_source, 0x00, ETH_ALEN );				if (priv->ule_dbit) {					// Dest MAC address not present --> generate our own.					memcpy( ethh->h_dest, eth_dest_addr, ETH_ALEN );				} else {					// Dest MAC address could be split across two TS cells.					// FIXME: implement.					printk( KERN_WARNING "%s: got destination MAC "						"address.\n", dev->name );					memcpy( ethh->h_dest, eth_dest_addr, ETH_ALEN );				}				ethh->h_proto = htons(priv->ule_sndu_type == ULE_LLC ?						      priv->ule_sndu_len : priv->ule_sndu_type);			}#endif			/* this includes the CRC32 _and_ dest mac, if !dbit! */			priv->ule_sndu_remain = priv->ule_sndu_len;			priv->ule_skb->dev = dev;		}		/* Copy data into our current skb. */		how_much = min(priv->ule_sndu_remain, (int)ts_remain);		if ((priv->ule_ethhdr_complete < ETH_ALEN) &&		    (priv->ule_sndu_type != ULE_BRIDGED)) {			ethh = (struct ethhdr *)priv->ule_skb->data;			if (! priv->ule_dbit) {				if (how_much >= (ETH_ALEN - priv->ule_ethhdr_complete)) {					/* copy dest mac address. */					memcpy(skb_put(priv->ule_skb,						       (ETH_ALEN - priv->ule_ethhdr_complete)),					       from_where,					       (ETH_ALEN - priv->ule_ethhdr_complete));					memset(ethh->h_source, 0x00, ETH_ALEN);					ethh->h_proto = htons(priv->ule_sndu_type == ULE_LLC ?							      priv->ule_sndu_len :							      priv->ule_sndu_type);					skb_put(priv->ule_skb, ETH_ALEN + 2);					how_much -= (ETH_ALEN - priv->ule_ethhdr_complete);					priv->ule_sndu_remain -= (ETH_ALEN -								  priv->ule_ethhdr_complete);					ts_remain -= (ETH_ALEN - priv->ule_ethhdr_complete);					from_where += (ETH_ALEN - priv->ule_ethhdr_complete);					priv->ule_ethhdr_complete = ETH_ALEN;				}			} else {				/* Generate whole Ethernet header. */				memcpy(ethh->h_dest, eth_dest_addr, ETH_ALEN);				memset(ethh->h_source, 0x00, ETH_ALEN);				ethh->h_proto = htons(priv->ule_sndu_type == ULE_LLC ?						      priv->ule_sndu_len : priv->ule_sndu_type);				skb_put(priv->ule_skb, ETH_HLEN);				priv->ule_ethhdr_complete = ETH_ALEN;			}		}		/* printk(KERN_WARNING "Copying %u bytes, ule_sndu_remain = %u, "		          "ule_sndu_len = %u.\n", how_much, priv->ule_sndu_remain,			  priv->ule_sndu_len); */		memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much);		priv->ule_sndu_remain -= how_much;		ts_remain -= how_much;		from_where += how_much;		if ((priv->ule_ethhdr_complete < ETH_ALEN) &&		    (priv->ule_sndu_type != ULE_BRIDGED)) {			priv->ule_ethhdr_complete += how_much;		}		/* Check for complete payload. */		if (priv->ule_sndu_remain <= 0) {			/* Check CRC32, we've got it in our skb already. */			unsigned short ulen = htons(priv->ule_sndu_len);			unsigned short utype = htons(priv->ule_sndu_type);			struct kvec iov[4] = {				{ &ulen, sizeof ulen },				{ &utype, sizeof utype },				{ NULL, 0 },				{ priv->ule_skb->data + ETH_HLEN,					priv->ule_skb->len - ETH_HLEN - 4 }			};			unsigned long ule_crc = ~0L, expected_crc;			if (priv->ule_dbit) {				/* Set D-bit for CRC32 verification,				 * if it was set originally. */				ulen |= 0x0080;			} else {				iov[2].iov_base = priv->ule_skb->data;				iov[2].iov_len = ETH_ALEN;			}			ule_crc = iov_crc32(ule_crc, iov, 4);			expected_crc = *((u8 *)priv->ule_skb->tail - 4) << 24 |				*((u8 *)priv->ule_skb->tail - 3) << 16 |				*((u8 *)priv->ule_skb->tail - 2) << 8 |				*((u8 *)priv->ule_skb->tail - 1);			if (ule_crc != expected_crc) {				printk(KERN_WARNING "CRC32 check %s: %#lx / %#lx.\n",				       ule_crc != expected_crc ? "FAILED" : "OK",				       ule_crc, expected_crc);				hexdump(priv->ule_skb->data + ETH_HLEN,					priv->ule_skb->len - ETH_HLEN);				((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;				((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++;				dev_kfree_skb(priv->ule_skb);			} else {				/* CRC32 was OK. Remove it from skb. */				priv->ule_skb->tail -= 4;				priv->ule_skb->len -= 4;				/* Stuff into kernel's protocol stack. */				priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev);				/* If D-bit is set (i.e. destination MAC address not present),				 * receive the packet anyhw. */				/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST) */					priv->ule_skb->pkt_type = PACKET_HOST;				((struct dvb_net_priv *) dev->priv)->stats.rx_packets++;				((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len;				netif_rx(priv->ule_skb);			}			/* Prepare for next SNDU. */			reset_ule(priv);		}		/* More data in current TS (look at the bytes following the CRC32)? */		if (ts_remain >= 2 && *((unsigned short *)from_where) != 0xFFFF) {			/* Next ULE SNDU starts right there. */			new_ts = 0;			priv->ule_skb = NULL;			priv->ule_sndu_type_1 = 0;			priv->ule_sndu_len = 0;			// printk(KERN_WARNING "More data in current TS: [%#x %#x %#x %#x]\n",			//	*(from_where + 0), *(from_where + 1),			//	*(from_where + 2), *(from_where + 3));			// printk(KERN_WARNING "ts @ %p, stopped @ %p:\n", ts, from_where + 0);			// hexdump(ts, 188);		} else {			new_ts = 1;			ts += TS_SZ;			if (priv->ule_skb == NULL) {				priv->need_pusi = 1;				priv->ule_sndu_type_1 = 0;				priv->ule_sndu_len = 0;			}		}	}	/* for all available TS cells */}static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,			       const u8 *buffer2, size_t buffer2_len,			       struct dmx_ts_feed *feed, enum dmx_success success){	struct net_device *dev = (struct net_device *)feed->priv;	if (buffer2 != 0)		printk(KERN_WARNING "buffer2 not 0: %p.\n", buffer2);	if (buffer1_len > 32768)		printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len);	/* printk("TS callback: %u bytes, %u TS cells @ %p.\n",	          buffer1_len, buffer1_len / TS_SZ, buffer1); */	dvb_net_ule(dev, buffer1, buffer1_len);	return 0;}static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len){        u8 *eth;        struct sk_buff *skb;	struct net_device_stats *stats = &(((struct dvb_net_priv *) dev->priv)->stats);	/* note: pkt_len includes a 32bit checksum */	if (pkt_len < 16) {		printk("%s: IP/MPE packet length = %d too small.\n",			dev->name, pkt_len);		stats->rx_errors++;		stats->rx_length_errors++;		return;	}/* it seems some ISPs manage to screw up here, so we have to * relax the error checks... */#if 0	if ((pkt[5] & 0xfd) != 0xc1) {		/* drop scrambled or broken packets */#else	if ((pkt[5] & 0x3c) != 0x00) {		/* drop scrambled */#endif		stats->rx_errors++;		stats->rx_crc_errors++;		return;	}	if (pkt[5] & 0x02) {		//FIXME: handle LLC/SNAP                stats->rx_dropped++;                return;        }	if (pkt[7]) {		/* FIXME: assemble datagram from multiple sections */		stats->rx_errors++;		stats->rx_frame_errors++;		return;	}	/* we have 14 byte ethernet header (ip header follows);	 * 12 byte MPE header; 4 byte checksum; + 2 byte alignment	 */	if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2))) {		//printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);		stats->rx_dropped++;		return;	}	skb_reserve(skb, 2);    /* longword align L3 header */	skb->dev = dev;	/* copy L3 payload */	eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14);	memcpy(eth + 14, pkt + 12, pkt_len - 12 - 4);	/* create ethernet header: */        eth[0]=pkt[0x0b];        eth[1]=pkt[0x0a];        eth[2]=pkt[0x09];        eth[3]=pkt[0x08];        eth[4]=pkt[0x04];        eth[5]=pkt[0x03];        eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0;	eth[12] = 0x08;	/* ETH_P_IP */	eth[13] = 0x00;	skb->protocol = dvb_net_eth_type_trans(skb, dev);        	stats->rx_packets++;	stats->rx_bytes+=skb->len;        netif_rx(skb);} static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,		 const u8 *buffer2, size_t buffer2_len,		 struct dmx_section_filter *filter,		 enum dmx_success success){        struct net_device *dev=(struct net_device *) filter->priv;	/**	 * we rely on the DVB API definition where exactly one complete	 * section is delivered in buffer1	 */	dvb_net_sec (dev, (u8*) buffer1, buffer1_len);	return 0;}static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev){	return 0;}static u8 mask_normal[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};static u8 mask_allmulti[6]={0xff, 0xff, 0xff, 0x00, 0x00, 0x00};static u8 mac_allmulti[6]={0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};static int dvb_net_filter_sec_set(struct net_device *dev,		   struct dmx_section_filter **secfilter,		   u8 *mac, u8 *mac_mask){	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;	int ret;	*secfilter=NULL;	ret = priv->secfeed->allocate_filter(priv->secfeed, secfilter);	if (ret<0) {		printk("%s: could not get filter\n", dev->name);		return ret;	}	(*secfilter)->priv=(void *) dev;	memset((*secfilter)->filter_value, 0x00, DMX_MAX_FILTER_SIZE);	memset((*secfilter)->filter_mask,  0x00, DMX_MAX_FILTER_SIZE);	memset((*secfilter)->filter_mode,  0xff, DMX_MAX_FILTER_SIZE);	(*secfilter)->filter_value[0]=0x3e;	(*secfilter)->filter_value[3]=mac[5];	(*secfilter)->filter_value[4]=mac[4];	(*secfilter)->filter_value[8]=mac[3];	(*secfilter)->filter_value[9]=mac[2];	(*secfilter)->filter_value[10]=mac[1];	(*secfilter)->filter_value[11]=mac[0];	(*secfilter)->filter_mask[0] = 0xff;	(*secfilter)->filter_mask[3] = mac_mask[5];	(*secfilter)->filter_mask[4] = mac_mask[4];	(*secfilter)->filter_mask[8] = mac_mask[3];	(*secfilter)->filter_mask[9] = mac_mask[2];	(*secfilter)->filter_mask[10] = mac_mask[1];	(*secfilter)->filter_mask[11]=mac_mask[0];	dprintk("%s: filter mac=%02x %02x %02x %02x %02x %02x\n",	       dev->name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);	dprintk("%s: filter mask=%02x %02x %02x %02x %02x %02x\n",	       dev->name, mac_mask[0], mac_mask[1], mac_mask[2],	       mac_mask[3], mac_mask[4], mac_mask[5]);	return 0;}static int dvb_net_feed_start(struct net_device *dev){	int ret, i;	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;        struct dmx_demux *demux = priv->demux;        unsigned char *mac = (unsigned char *) dev->dev_addr;			dprintk("%s: rx_mode %i\n", __FUNCTION__, priv->rx_mode);	if (priv->secfeed || priv->secfilter || priv->multi_secfilter[0])		printk("%s: BUG %d\n", __FUNCTION__, __LINE__);	priv->secfeed=NULL;	priv->secfilter=NULL;	priv->tsfeed = NULL;	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {	dprintk("%s: alloc secfeed\n", __FUNCTION__);	ret=demux->allocate_section_feed(demux, &priv->secfeed, 					 dvb_net_sec_callback);	if (ret<0) {		printk("%s: could not allocate section feed\n", dev->name);		return ret;	}	ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 1);	if (ret<0) {		printk("%s: could not set section feed\n", dev->name);		priv->demux->release_section_feed(priv->demux, priv->secfeed);		priv->secfeed=NULL;		return ret;	}	if (priv->rx_mode != RX_MODE_PROMISC) {		dprintk("%s: set secfilter\n", __FUNCTION__);			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);	}	switch (priv->rx_mode) {	case RX_MODE_MULTI:		for (i = 0; i < priv->multi_num; i++) {			dprintk("%s: set multi_secfilter[%d]\n", __FUNCTION__, i);				dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],					   priv->multi_macs[i], mask_normal);		}		break;	case RX_MODE_ALL_MULTI:		priv->multi_num=1;		dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__);			dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],				   mac_allmulti, mask_allmulti);		break;	case RX_MODE_PROMISC:		priv->multi_num=0;		dprintk("%s: set secfilter\n", __FUNCTION__);			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);		break;	}		dprintk("%s: start filtering\n", __FUNCTION__);	priv->secfeed->start_filtering(priv->secfeed);	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {		struct timespec timeout = { 0, 30000000 }; // 30 msec		/* we have payloads encapsulated in TS */		dprintk("%s: alloc tsfeed\n", __FUNCTION__);		ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);		if (ret < 0) {			printk("%s: could not allocate ts feed\n", dev->name);			return ret;		}		/* Set netdevice pointer for ts decaps callback. */		priv->tsfeed->priv = (void *)dev;		ret = priv->tsfeed->set(priv->tsfeed, priv->pid,					TS_PACKET, DMX_TS_PES_OTHER,					188 * 100, /* nr. of bytes delivered per callback */					32768,     /* circular buffer size */					0,         /* descramble */					timeout);		if (ret < 0) {			printk("%s: could not set ts feed\n", dev->name);			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);			priv->tsfeed = NULL;			return ret;		}		dprintk("%s: start filtering\n", __FUNCTION__);		priv->tsfeed->start_filtering(priv->tsfeed);	} else		return -EINVAL;	return 0;}static int dvb_net_feed_stop(struct net_device *dev){	struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;

⌨️ 快捷键说明

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