diff options
author | Johannes Stezenbach <devnull@localhost> | 2003-06-24 16:39:01 +0000 |
---|---|---|
committer | Johannes Stezenbach <devnull@localhost> | 2003-06-24 16:39:01 +0000 |
commit | 437d4fd4b8844edaaa924dd0d8630c15e0a004c7 (patch) | |
tree | dd0a746dde83a54317adb355719c483e06a97105 /linux/drivers | |
parent | 9d17b86119fc38f8600e5a4dadf6ade4d09dfe03 (diff) | |
download | mediapointer-dvb-s2-437d4fd4b8844edaaa924dd0d8630c15e0a004c7.tar.gz mediapointer-dvb-s2-437d4fd4b8844edaaa924dd0d8630c15e0a004c7.tar.bz2 |
- set check-CRC flag on section filter to drop broken packets
- some more debug prints in filter handling code
- cleaned up and commented packet reception handler
- formatting fixes
Diffstat (limited to 'linux/drivers')
-rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_net.c | 146 |
1 files changed, 96 insertions, 50 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/dvb_net.c b/linux/drivers/media/dvb/dvb-core/dvb_net.c index b8e446068..1924ba76d 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_net.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_net.c @@ -52,7 +52,11 @@ struct dvb_net_priv { int multi_num; struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX]; unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6]; - int mode; + int rx_mode; +#define RX_MODE_UNI 0 +#define RX_MODE_MULTI 1 +#define RX_MODE_ALL_MULTI 2 +#define RX_MODE_PROMISC 3 struct work_struct wq; }; @@ -71,12 +75,12 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb, struct ethhdr *eth; unsigned char *rawp; - skb->mac.raw=skb->data; - skb_pull(skb,dev->hard_header_len); - eth= skb->mac.ethernet; + skb->mac.raw = skb->data; + skb_pull(skb, dev->hard_header_len); + eth = skb->mac.ethernet; - if(*eth->h_dest & 1) { - if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN) == 0) + if (*eth->h_dest & 1) { + if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0) skb->pkt_type = PACKET_BROADCAST; else skb->pkt_type = PACKET_MULTICAST; @@ -93,7 +97,7 @@ static unsigned short dvb_net_eth_type_trans(struct sk_buff *skb, * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This * won't work for fault tolerant netware but does for the rest. */ - if (*(unsigned short *)rawp == 0xFFFF) + if (*(unsigned short *) rawp == 0xFFFF) return htons(ETH_P_802_3); /** @@ -108,22 +112,48 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len) u8 *eth; struct sk_buff *skb; - if (pkt_len < 13) { + /* 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); + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++; + return; + } + if ((pkt[5] & 0xfd) != 0xc1) { + /* drop scrambled or broken packets */ + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++; + return; + } + if (pkt[5] & 0x02) { + //FIXME: handle LLC/SNAP + ((struct dvb_net_priv *) dev->priv)->stats.rx_dropped++; + return; + } + if (pkt[7]) { + /* FIXME: assemble datagram from multiple sections */ + ((struct dvb_net_priv *) dev->priv)->stats.rx_errors++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++; return; } - if (!(skb = dev_alloc_skb(pkt_len+2))) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", - dev->name); - ((struct dvb_net_priv *)dev->priv)->stats.rx_dropped++; + /* 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); + ((struct dvb_net_priv *) dev->priv)->stats.rx_dropped++; return; } + skb_reserve(skb, 2); /* longword align L3 header */ + skb->dev = dev; - eth=(u8 *) skb_put(skb, pkt_len+2); - memcpy(eth+14, (void*)pkt+12, pkt_len-12); + /* 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]; @@ -133,14 +163,13 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len) eth[6] = eth[7] = eth[8] = eth[9] = eth[10] = eth[11] = 0; - eth[12] = 0x08; + eth[12] = 0x08; /* ETH_P_IP */ eth[13] = 0x00; - skb->protocol = dvb_net_eth_type_trans(skb,dev); - skb->dev = dev; + skb->protocol = dvb_net_eth_type_trans(skb, dev); - ((struct dvb_net_priv *)dev->priv)->stats.rx_packets++; - ((struct dvb_net_priv *)dev->priv)->stats.rx_bytes += skb->len; + ((struct dvb_net_priv *) dev->priv)->stats.rx_packets++; + ((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += skb->len; netif_rx(skb); } @@ -225,47 +254,57 @@ static int dvb_net_feed_start (struct net_device *dev) 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 = 0; priv->secfilter = 0; - ret=demux->allocate_section_feed(demux, &priv->secfeed, - dvb_net_callback); + dprintk("%s: alloc secfeed\n", __FUNCTION__); + ret = demux->allocate_section_feed(demux, &priv->secfeed, + dvb_net_callback); if (ret < 0) { - printk("%s: could not get section feed\n", dev->name); + printk("%s: could not allocate section feed\n", dev->name); return ret; } - ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 0, 0); + 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=0; + priv->secfeed = 0; return ret; } - if (priv->mode < 3) + if (priv->rx_mode != RX_MODE_PROMISC) { + dprintk("%s: set secfilter\n", __FUNCTION__); dvb_net_filter_set(dev, &priv->secfilter, mac, mask_normal); + } - dprintk("%s: mode %i\n", __FUNCTION__, priv->mode); - - switch (priv->mode) { - case 1: - for (i=0; i<priv->multi_num; i++) + 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_set(dev, &priv->multi_secfilter[i], priv->multi_macs[i], mask_normal); + } break; - case 2: + case RX_MODE_ALL_MULTI: priv->multi_num = 1; + dprintk("%s: set multi_secfilter[0]\n", __FUNCTION__); dvb_net_filter_set(dev, &priv->multi_secfilter[0], mac_allmulti, mask_allmulti); break; - case 3: + case RX_MODE_PROMISC: priv->multi_num = 0; + dprintk("%s: set secfilter\n", __FUNCTION__); dvb_net_filter_set(dev, &priv->secfilter, mac, mask_promisc); break; } + dprintk("%s: start filtering\n", __FUNCTION__); priv->secfeed->start_filtering(priv->secfeed); return 0; } @@ -276,24 +315,31 @@ static void dvb_net_feed_stop (struct net_device *dev) struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; int i; + dprintk("%s\n", __FUNCTION__); if (priv->secfeed) { - if (priv->secfeed->is_filtering) + if (priv->secfeed->is_filtering) { + dprintk("%s: stop secfeed\n", __FUNCTION__); priv->secfeed->stop_filtering(priv->secfeed); + } - if (priv->secfilter) + if (priv->secfilter) { + dprintk("%s: release secfilter\n", __FUNCTION__); priv->secfeed->release_filter(priv->secfeed, priv->secfilter); - priv->secfilter = 0; + priv->secfilter = 0; + } - for (i=0; i<priv->multi_num; i++) { - if (priv->multi_secfilter[i]) + for (i = 0; i < priv->multi_num; i++) { + if (priv->multi_secfilter[i]) { + dprintk("%s: release multi_filter[%d]\n", __FUNCTION__, i); priv->secfeed->release_filter(priv->secfeed, priv->multi_secfilter[i]); - priv->multi_secfilter[i]=0; + priv->multi_secfilter[i] = 0; + } } priv->demux->release_section_feed(priv->demux, priv->secfeed); - priv->secfeed=0; + priv->secfeed = 0; } else printk("%s: no feed to stop\n", dev->name); } @@ -303,7 +349,7 @@ static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc) { struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; - if (priv->multi_num==DVB_NET_MULTICAST_MAX) + if (priv->multi_num == DVB_NET_MULTICAST_MAX) return -ENOMEM; memcpy(priv->multi_macs[priv->multi_num], mc->dmi_addr, 6); @@ -320,27 +366,27 @@ static void tq_set_multicast_list (void *data) dvb_net_feed_stop(dev); - priv->mode = 0; + priv->rx_mode = RX_MODE_UNI; if (dev->flags & IFF_PROMISC) { dprintk("%s: promiscuous mode\n", dev->name); - priv->mode = 3; - } else if((dev->flags & IFF_ALLMULTI)) { + priv->rx_mode = RX_MODE_PROMISC; + } else if ((dev->flags & IFF_ALLMULTI)) { dprintk("%s: allmulti mode\n", dev->name); - priv->mode = 2; - } else if(dev->mc_count) { + priv->rx_mode = RX_MODE_ALL_MULTI; + } else if (dev->mc_count) { int mci; struct dev_mc_list *mc; dprintk("%s: set_mc_list, %d entries\n", dev->name, dev->mc_count); - priv->mode = 1; + priv->rx_mode = RX_MODE_MULTI; priv->multi_num = 0; - for (mci=0, mc=dev->mc_list; - mci<dev->mc_count; - mc=mc->next, mci++) { + for (mci = 0, mc = dev->mc_list; + mci < dev->mc_count; + mc = mc->next, mci++) { dvb_set_mc_filter(dev, mc); } } @@ -475,7 +521,7 @@ static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid) memset(priv, 0, sizeof(struct dvb_net_priv)); priv->demux = demux; priv->pid = pid; - priv->mode = 0; + priv->rx_mode = RX_MODE_UNI; INIT_WORK(&priv->wq, tq_set_multicast_list, net); |