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 + -
显示快捷键?