summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorJohannes Stezenbach <devnull@localhost>2003-06-24 16:39:01 +0000
committerJohannes Stezenbach <devnull@localhost>2003-06-24 16:39:01 +0000
commit437d4fd4b8844edaaa924dd0d8630c15e0a004c7 (patch)
treedd0a746dde83a54317adb355719c483e06a97105 /linux
parent9d17b86119fc38f8600e5a4dadf6ade4d09dfe03 (diff)
downloadmediapointer-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')
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_net.c146
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);