aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/netdevices.txt2
-rw-r--r--drivers/atm/eni.c27
-rw-r--r--drivers/atm/fore200e.c4
-rw-r--r--drivers/atm/he.c3
-rw-r--r--drivers/atm/he.h2
-rw-r--r--drivers/net/hamradio/6pack.c4
-rw-r--r--drivers/net/hamradio/baycom_epp.c4
-rw-r--r--drivers/net/hamradio/bpqether.c10
-rw-r--r--drivers/net/hamradio/dmascc.c4
-rw-r--r--drivers/net/hamradio/hdlcdrv.c4
-rw-r--r--drivers/net/hamradio/mkiss.c4
-rw-r--r--drivers/net/hamradio/scc.c5
-rw-r--r--drivers/net/hamradio/yam.c4
-rw-r--r--drivers/net/slip.c30
-rw-r--r--drivers/net/tg3.c4
-rw-r--r--include/linux/netfilter_ipv4.h3
-rw-r--r--include/linux/tc_act/tc_defact.h21
-rw-r--r--include/net/act_generic.h142
-rw-r--r--include/net/ax25.h8
-rw-r--r--include/net/ipv6.h2
-rw-r--r--include/net/tc_act/tc_defact.h13
-rw-r--r--include/net/tcp.h11
-rw-r--r--net/ax25/ax25_ds_subr.c3
-rw-r--r--net/ax25/ax25_out.c3
-rw-r--r--net/core/dev.c13
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c51
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c9
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c54
-rw-r--r--net/ipv4/tcp_output.c25
-rw-r--r--net/ipv6/af_inet6.c1
-rw-r--r--net/ipv6/exthdrs_core.c11
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/sched/Kconfig10
-rw-r--r--net/sched/Makefile11
-rw-r--r--net/sched/cls_fw.c31
-rw-r--r--net/sched/simple.c107
-rw-r--r--security/selinux/hooks.c3
38 files changed, 526 insertions, 122 deletions
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index 1509f3aff96..3c0a5ba614d 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -51,6 +51,8 @@ dev->hard_start_xmit:
set_multicast_list
Context: BHs disabled
Notes: netif_queue_stopped() is guaranteed false
+ Interrupts must be enabled when calling hard_start_xmit.
+ (Interrupts must also be enabled when enabling the BH handler.)
Return codes:
o NETDEV_TX_OK everything ok.
o NETDEV_TX_BUSY Cannot transmit packet, try later
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 78e34ee79df..10da3693476 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -59,7 +59,6 @@
* - doesn't support OAM cells
* - eni_put_free may hang if not putting memory fragments that _complete_
* 2^n block (never happens in real life, though)
- * - keeps IRQ even if initialization fails
*/
@@ -1802,22 +1801,22 @@ static int __devinit eni_start(struct atm_dev *dev)
if (request_irq(eni_dev->irq,&eni_int,SA_SHIRQ,DEV_LABEL,dev)) {
printk(KERN_ERR DEV_LABEL "(itf %d): IRQ%d is already in use\n",
dev->number,eni_dev->irq);
- return -EAGAIN;
+ error = -EAGAIN;
+ goto out;
}
- /* @@@ should release IRQ on error */
pci_set_master(eni_dev->pci_dev);
if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
(eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
printk(KERN_ERR DEV_LABEL "(itf %d): can't enable memory+"
"master (0x%02x)\n",dev->number,error);
- return error;
+ goto free_irq;
}
if ((error = pci_write_config_byte(eni_dev->pci_dev,PCI_TONGA_CTRL,
END_SWAP_DMA))) {
printk(KERN_ERR DEV_LABEL "(itf %d): can't set endian swap "
"(0x%02x)\n",dev->number,error);
- return error;
+ goto free_irq;
}
/* determine addresses of internal tables */
eni_dev->vci = eni_dev->ram;
@@ -1839,7 +1838,8 @@ static int __devinit eni_start(struct atm_dev *dev)
if (!eni_dev->free_list) {
printk(KERN_ERR DEV_LABEL "(itf %d): couldn't get free page\n",
dev->number);
- return -ENOMEM;
+ error = -ENOMEM;
+ goto free_irq;
}
eni_dev->free_len = 0;
eni_put_free(eni_dev,buf,buffer_mem);
@@ -1855,17 +1855,26 @@ static int __devinit eni_start(struct atm_dev *dev)
*/
eni_out(0xffffffff,MID_IE);
error = start_tx(dev);
- if (error) return error;
+ if (error) goto free_list;
error = start_rx(dev);
- if (error) return error;
+ if (error) goto free_list;
error = dev->phy->start(dev);
- if (error) return error;
+ if (error) goto free_list;
eni_out(eni_in(MID_MC_S) | (1 << MID_INT_SEL_SHIFT) |
MID_TX_LOCK_MODE | MID_DMA_ENABLE | MID_TX_ENABLE | MID_RX_ENABLE,
MID_MC_S);
/* Tonga uses SBus INTReq1 */
(void) eni_in(MID_ISA); /* clear Midway interrupts */
return 0;
+
+free_list:
+ kfree(eni_dev->free_list);
+
+free_irq:
+ free_irq(eni_dev->irq, eni_dev);
+
+out:
+ return error;
}
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 196b3364462..9e65bfb85ba 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -2792,8 +2792,6 @@ static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev)
fore200e = pci_get_drvdata(pci_dev);
- list_del(&fore200e->entry);
-
fore200e_shutdown(fore200e);
kfree(fore200e);
pci_disable_device(pci_dev);
@@ -2850,7 +2848,7 @@ fore200e_module_init(void)
}
#ifdef CONFIG_ATM_FORE200E_PCA
- if (!pci_module_init(&fore200e_pca_driver))
+ if (!pci_register_driver(&fore200e_pca_driver))
return 0;
#endif
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index c2c31a5f451..3022c548a13 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -70,6 +70,7 @@
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/byteorder.h>
#include <asm/uaccess.h>
@@ -371,7 +372,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
if (pci_enable_device(pci_dev))
return -EIO;
- if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0) {
+ if (pci_set_dma_mask(pci_dev, DMA_32BIT_MASK) != 0) {
printk(KERN_WARNING "he: no suitable dma available\n");
err = -EIO;
goto init_one_failure;
diff --git a/drivers/atm/he.h b/drivers/atm/he.h
index 1a903859343..1dc277547a7 100644
--- a/drivers/atm/he.h
+++ b/drivers/atm/he.h
@@ -380,8 +380,6 @@ struct he_vcc
#define PCI_VENDOR_ID_FORE 0x1127
#define PCI_DEVICE_ID_FORE_HE 0x400
-#define HE_DMA_MASK 0xffffffff
-
#define GEN_CNTL_0 0x40
#define INT_PROC_ENBL (1<<25)
#define SLAVE_ENDIAN_MODE (1<<16)
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 067b353e1cb..89454915b85 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -394,13 +394,11 @@ static void sp_bump(struct sixpack *sp, char cmd)
if ((skb = dev_alloc_skb(count)) == NULL)
goto out_mem;
- skb->dev = sp->dev;
ptr = skb_put(skb, count);
*ptr++ = cmd; /* KISS command */
memcpy(ptr, sp->cooked_buf + 1, count);
- skb->mac.raw = skb->data;
- skb->protocol = htons(ETH_P_AX25);
+ skb->protocol = ax25_type_trans(skb, sp->dev);
netif_rx(skb);
sp->dev->last_rx = jiffies;
sp->stats.rx_packets++;
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index e8cb87d906f..1c563f905a5 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -601,12 +601,10 @@ static void do_rxpacket(struct net_device *dev)
bc->stats.rx_dropped++;
return;
}
- skb->dev = dev;
cp = skb_put(skb, pktlen);
*cp++ = 0; /* KISS kludge */
memcpy(cp, bc->hdlcrx.buf, pktlen - 1);
- skb->protocol = htons(ETH_P_AX25);
- skb->mac.raw = skb->data;
+ skb->protocol = ax25_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
bc->stats.rx_packets++;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index ef1a359e227..ba9f0580e1f 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -211,11 +211,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
ptr = skb_push(skb, 1);
*ptr = 0;
- skb->dev = dev;
- skb->protocol = htons(ETH_P_AX25);
- skb->mac.raw = skb->data;
- skb->pkt_type = PACKET_HOST;
-
+ skb->protocol = ax25_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
unlock:
@@ -272,8 +268,6 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
skb = newskb;
}
- skb->protocol = htons(ETH_P_AX25);
-
ptr = skb_push(skb, 2);
*ptr++ = (size + 5) % 256;
@@ -287,7 +281,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
return -ENODEV;
}
- skb->dev = dev;
+ skb->protocol = ax25_type_trans(skb, dev);
skb->nh.raw = skb->data;
dev->hard_header(skb, dev, ETH_P_BPQ, bpq->dest_addr, NULL, 0);
bpq->stats.tx_packets++;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index f3269b70a8c..f515245a3fd 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -1306,9 +1306,7 @@ static void rx_bh(void *arg)
data = skb_put(skb, cb + 1);
data[0] = 0;
memcpy(&data[1], priv->rx_buf[i], cb);
- skb->dev = priv->dev;
- skb->protocol = ntohs(ETH_P_AX25);
- skb->mac.raw = skb->data;
+ skb->protocol = ax25_type_trans(skb, priv->dev);
netif_rx(skb);
priv->dev->last_rx = jiffies;
priv->stats.rx_packets++;
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index b89959a596d..b4c836e4fe8 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -174,12 +174,10 @@ static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s)
s->stats.rx_dropped++;
return;
}
- skb->dev = dev;
cp = skb_put(skb, pkt_len);
*cp++ = 0; /* KISS kludge */
memcpy(cp, s->hdlcrx.buffer, pkt_len - 1);
- skb->protocol = htons(ETH_P_AX25);
- skb->mac.raw = skb->data;
+ skb->protocol = ax25_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
s->stats.rx_packets++;
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index d9ea080aea0..62790511098 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -332,12 +332,10 @@ static void ax_bump(struct ax_disp *ax)
return;
}
- skb->dev = ax->dev;
spin_lock_bh(&ax->buflock);
memcpy(skb_put(skb,count), ax->rbuff, count);
spin_unlock_bh(&ax->buflock);
- skb->mac.raw = skb->data;
- skb->protocol = htons(ETH_P_AX25);
+ skb->protocol = ax25_type_trans(skb, ax->dev);
netif_rx(skb);
ax->dev->last_rx = jiffies;
ax->rx_packets++;
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index ce9e7af020d..ece1b1a1318 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1630,10 +1630,7 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
scc->dev_stat.rx_packets++;
scc->dev_stat.rx_bytes += skb->len;
- skb->dev = scc->dev;
- skb->protocol = htons(ETH_P_AX25);
- skb->mac.raw = skb->data;
- skb->pkt_type = PACKET_HOST;
+ skb->protocol = ax25_type_trans(skb, scc->dev);
netif_rx(skb);
scc->dev->last_rx = jiffies;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index fd7b00fe38e..41213ef602d 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -522,12 +522,10 @@ static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp)
++yp->stats.rx_dropped;
} else {
unsigned char *cp;
- skb->dev = dev;
cp = skb_put(skb, pkt_len);
*cp++ = 0; /* KISS kludge */
memcpy(cp, yp->rx_buf, pkt_len - 1);
- skb->protocol = htons(ETH_P_AX25);
- skb->mac.raw = skb->data;
+ skb->protocol = ax25_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
++yp->stats.rx_packets;
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 4ce52f5f241..8f7841c0374 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -185,15 +185,12 @@ sl_alloc_bufs(struct slip *sl, int mtu)
/* Cleanup */
err_exit:
#ifdef SL_INCLUDE_CSLIP
- if (cbuff)
- kfree(cbuff);
+ kfree(cbuff);
if (slcomp)
slhc_free(slcomp);
#endif
- if (xbuff)
- kfree(xbuff);
- if (rbuff)
- kfree(rbuff);
+ kfree(xbuff);
+ kfree(rbuff);
return err;
}
@@ -204,13 +201,13 @@ sl_free_bufs(struct slip *sl)
void * tmp;
/* Free all SLIP frame buffers. */
- if ((tmp = xchg(&sl->rbuff, NULL)) != NULL)
- kfree(tmp);
- if ((tmp = xchg(&sl->xbuff, NULL)) != NULL)
- kfree(tmp);
+ tmp = xchg(&sl->rbuff, NULL);
+ kfree(tmp);
+ tmp = xchg(&sl->xbuff, NULL);
+ kfree(tmp);
#ifdef SL_INCLUDE_CSLIP
- if ((tmp = xchg(&sl->cbuff, NULL)) != NULL)
- kfree(tmp);
+ tmp = xchg(&sl->cbuff, NULL);
+ kfree(tmp);
if ((tmp = xchg(&sl->slcomp, NULL)) != NULL)
slhc_free(tmp);
#endif
@@ -297,13 +294,10 @@ done_on_bh:
spin_unlock_bh(&sl->lock);
done:
- if (xbuff)
- kfree(xbuff);
- if (rbuff)
- kfree(rbuff);
+ kfree(xbuff);
+ kfree(rbuff);
#ifdef SL_INCLUDE_CSLIP
- if (cbuff)
- kfree(cbuff);
+ kfree(cbuff);
#endif
return err;
}
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index f65ca3b2da6..10d476153ee 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -61,8 +61,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.25"
-#define DRV_MODULE_RELDATE "March 24, 2005"
+#define DRV_MODULE_VERSION "3.26"
+#define DRV_MODULE_RELDATE "April 24, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index c9bacf9b243..9e5750079e0 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -62,6 +62,9 @@ enum nf_ip_hook_priorities {
NF_IP_PRI_FILTER = 0,
NF_IP_PRI_NAT_SRC = 100,
NF_IP_PRI_SELINUX_LAST = 225,
+ NF_IP_PRI_CONNTRACK_HELPER = INT_MAX - 2,
+ NF_IP_PRI_NAT_SEQ_ADJUST = INT_MAX - 1,
+ NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
NF_IP_PRI_LAST = INT_MAX,
};
diff --git a/include/linux/tc_act/tc_defact.h b/include/linux/tc_act/tc_defact.h
new file mode 100644
index 00000000000..964f473af0f
--- /dev/null
+++ b/include/linux/tc_act/tc_defact.h
@@ -0,0 +1,21 @@
+#ifndef __LINUX_TC_DEF_H
+#define __LINUX_TC_DEF_H
+
+#include <linux/pkt_cls.h>
+
+struct tc_defact
+{
+ tc_gen;
+};
+
+enum
+{
+ TCA_DEF_UNSPEC,
+ TCA_DEF_TM,
+ TCA_DEF_PARMS,
+ TCA_DEF_DATA,
+ __TCA_DEF_MAX
+};
+#define TCA_DEF_MAX (__TCA_DEF_MAX - 1)
+
+#endif
diff --git a/include/net/act_generic.h b/include/net/act_generic.h
new file mode 100644
index 00000000000..95b120781c1
--- /dev/null
+++ b/include/net/act_generic.h
@@ -0,0 +1,142 @@
+/*
+ * include/net/act_generic.h
+ *
+*/
+#ifndef ACT_GENERIC_H
+#define ACT_GENERIC_H
+static inline int tcf_defact_release(struct tcf_defact *p, int bind)
+{
+ int ret = 0;
+ if (p) {
+ if (bind) {
+ p->bindcnt--;
+ }
+ p->refcnt--;
+ if (p->bindcnt <= 0 && p->refcnt <= 0) {
+ kfree(p->defdata);
+ tcf_hash_destroy(p);
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
+static inline int
+alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
+{
+ p->defdata = kmalloc(datalen, GFP_KERNEL);
+ if (p->defdata == NULL)
+ return -ENOMEM;
+ p->datalen = datalen;
+ memcpy(p->defdata, defdata, datalen);
+ return 0;
+}
+
+static inline int
+realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata)
+{
+ /* safer to be just brute force for now */
+ kfree(p->defdata);
+ return alloc_defdata(p, datalen, defdata);
+}
+
+static inline int
+tcf_defact_init(struct rtattr *rta, struct rtattr *est,
+ struct tc_action *a, int ovr, int bind)
+{
+ struct rtattr *tb[TCA_DEF_MAX];
+ struct tc_defact *parm;
+ struct tcf_defact *p;
+ void *defdata;
+ u32 datalen = 0;
+ int ret = 0;
+
+ if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0)
+ return -EINVAL;
+
+ if (tb[TCA_DEF_PARMS - 1] == NULL ||
+ RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm))
+ return -EINVAL;
+
+ parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]);
+ defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]);
+ if (defdata == NULL)
+ return -EINVAL;
+
+ datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]);
+ if (datalen <= 0)
+ return -EINVAL;
+
+ p = tcf_hash_check(parm->index, a, ovr, bind);
+ if (p == NULL) {
+ p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind);
+ if (p == NULL)
+ return -ENOMEM;
+
+ ret = alloc_defdata(p, datalen, defdata);
+ if (ret < 0) {
+ kfree(p);
+ return ret;
+ }
+ ret = ACT_P_CREATED;
+ } else {
+ if (!ovr) {
+ tcf_defact_release(p, bind);
+ return -EEXIST;
+ }
+ realloc_defdata(p, datalen, defdata);
+ }
+
+ spin_lock_bh(&p->lock);
+ p->action = parm->action;
+ spin_unlock_bh(&p->lock);
+ if (ret == ACT_P_CREATED)
+ tcf_hash_insert(p);
+ return ret;
+}
+
+static inline int tcf_defact_cleanup(struct tc_action *a, int bind)
+{
+ struct tcf_defact *p = PRIV(a, defact);
+
+ if (p != NULL)
+ return tcf_defact_release(p, bind);
+ return 0;
+}
+
+static inline int
+tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
+{
+ unsigned char *b = skb->tail;
+ struct tc_defact opt;
+ struct tcf_defact *p = PRIV(a, defact);
+ struct tcf_t t;
+
+ opt.index = p->index;
+ opt.refcnt = p->refcnt - ref;
+ opt.bindcnt = p->bindcnt - bind;
+ opt.action = p->action;
+ RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
+ RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata);
+ t.install = jiffies_to_clock_t(jiffies - p->tm.install);
+ t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse);
+ t.expires = jiffies_to_clock_t(p->tm.expires);
+ RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t);
+ return skb->len;
+
+rtattr_failure:
+ skb_trim(skb, b - skb->data);
+ return -1;
+}
+
+#define tca_use_default_ops \
+ .dump = tcf_defact_dump, \
+ .cleanup = tcf_defact_cleanup, \
+ .init = tcf_defact_init, \
+ .walk = tcf_generic_walker, \
+
+#define tca_use_default_defines(name) \
+ static u32 idx_gen; \
+ static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \
+ static DEFINE_RWLOCK(##name_lock);
+#endif /* _NET_ACT_GENERIC_H */
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 875edbba396..9e6368a5454 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -220,6 +220,14 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25)
}
}
+static inline unsigned short ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+ skb->dev = dev;
+ skb->pkt_type = PACKET_HOST;
+ skb->mac.raw = skb->data;
+ return htons(ETH_P_AX25);
+}
+
/* af_ax25.c */
extern struct hlist_head ax25_list;
extern spinlock_t ax25_list_lock;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 87c45cbfbaf..771b47e30f8 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -416,7 +416,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb,
u8 *proto);
extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
- u8 *nexthdrp, int len);
+ u8 *nexthdrp);
extern int ipv6_ext_hdr(u8 nexthdr);
diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h
new file mode 100644
index 00000000000..463aa671f95
--- /dev/null
+++ b/include/net/tc_act/tc_defact.h
@@ -0,0 +1,13 @@
+#ifndef __NET_TC_DEF_H
+#define __NET_TC_DEF_H
+
+#include <net/act_api.h>
+
+struct tcf_defact
+{
+ tca_gen(defact);
+ u32 datalen;
+ void *defdata;
+};
+
+#endif
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 503810a70e2..9355ae5b1d7 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1417,19 +1417,20 @@ tcp_nagle_check(const struct tcp_sock *tp, const struct sk_buff *skb,
tcp_minshall_check(tp))));
}
-extern void tcp_set_skb_tso_segs(struct sk_buff *, unsigned int);
+extern void tcp_set_skb_tso_segs(struct sock *, struct sk_buff *);
/* This checks if the data bearing packet SKB (usually sk->sk_send_head)
* should be put on the wire right now.
*/
-static __inline__ int tcp_snd_test(const struct tcp_sock *tp,
+static __inline__ int tcp_snd_test(struct sock *sk,
struct sk_buff *skb,
unsigned cur_mss, int nonagle)
{
+ struct tcp_sock *tp = tcp_sk(sk);
int pkts = tcp_skb_pcount(skb);
if (!pkts) {
- tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+ tcp_set_skb_tso_segs(sk, skb);
pkts = tcp_skb_pcount(skb);
}
@@ -1490,7 +1491,7 @@ static __inline__ void __tcp_push_pending_frames(struct sock *sk,
if (skb) {
if (!tcp_skb_is_last(sk, skb))
nonagle = TCP_NAGLE_PUSH;
- if (!tcp_snd_test(tp, skb, cur_mss, nonagle) ||
+ if (!tcp_snd_test(sk, skb, cur_mss, nonagle) ||
tcp_write_xmit(sk, nonagle))
tcp_check_probe_timer(sk, tp);
}
@@ -1508,7 +1509,7 @@ static __inline__ int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp)
struct sk_buff *skb = sk->sk_send_head;
return (skb &&
- tcp_snd_test(tp, skb, tcp_current_mss(sk, 1),
+ tcp_snd_test(sk, skb, tcp_current_mss(sk, 1),
tcp_skb_is_last(sk, skb) ? TCP_NAGLE_PUSH : tp->nonagle));
}
diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c
index 10ffd2beba3..1d4ab641f82 100644
--- a/net/ax25/ax25_ds_subr.c
+++ b/net/ax25/ax25_ds_subr.c
@@ -143,8 +143,7 @@ static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char p
*p++ = cmd;
*p++ = param;
- skb->dev = ax25_dev->dev;
- skb->protocol = htons(ETH_P_AX25);
+ skb->protocol = ax25_type_trans(skb, ax25_dev->dev);
dev_queue_xmit(skb);
}
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index 94557b1a1fa..5fc048dcd39 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -351,8 +351,7 @@ void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned char *ptr;
- skb->protocol = htons(ETH_P_AX25);
- skb->dev = ax25_fwd_dev(dev);
+ skb->protocol = ax25_type_trans(skb, ax25_fwd_dev(dev));
ptr = skb_push(skb, 1);
*ptr = 0x00; /* KISS */
diff --git a/net/core/dev.c b/net/core/dev.c
index 42344d90369..7bd4cd4502c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1214,6 +1214,19 @@ int __skb_linearize(struct sk_buff *skb, int gfp_mask)
* A negative errno code is returned on a failure. A success does not
* guarantee the frame will be transmitted as it may be dropped due
* to congestion or traffic shaping.
+ *
+ * -----------------------------------------------------------------------------------
+ * I notice this method can also return errors from the queue disciplines,
+ * including NET_XMIT_DROP, which is a positive value. So, errors can also
+ * be positive.
+ *
+ * Regardless of the return value, the skb is consumed, so it is currently
+ * difficult to retry a send to this method. (You can bump the ref count
+ * before sending to hold a reference for retry if you are careful.)
+ *
+ * When calling this method, interrupts MUST be enabled. This is because
+ * the BH enable code must have IRQs enabled so that it will not deadlock.
+ * --BLG
*/
int dev_queue_xmit(struct sk_buff *skb)
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index e800b16fc92..2b87c1974be 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -770,6 +770,7 @@ static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
{
[TH_SYN] = 1,
[TH_SYN|TH_ACK] = 1,
+ [TH_SYN|TH_ACK|TH_PUSH] = 1,
[TH_RST] = 1,
[TH_RST|TH_ACK] = 1,
[TH_RST|TH_ACK|TH_PUSH] = 1,
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 80a7bde2a57..0c29ccf62a8 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -401,6 +401,16 @@ static unsigned int ip_confirm(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
+ /* We've seen it coming out the other side: confirm it */
+ return ip_conntrack_confirm(pskb);
+}
+
+static unsigned int ip_conntrack_help(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
@@ -412,9 +422,7 @@ static unsigned int ip_confirm(unsigned int hooknum,
if (ret != NF_ACCEPT)
return ret;
}
-
- /* We've seen it coming out the other side: confirm it */
- return ip_conntrack_confirm(pskb);
+ return NF_ACCEPT;
}
static unsigned int ip_conntrack_defrag(unsigned int hooknum,
@@ -516,13 +524,30 @@ static struct nf_hook_ops ip_conntrack_local_out_ops = {
.priority = NF_IP_PRI_CONNTRACK,
};
+/* helpers */
+static struct nf_hook_ops ip_conntrack_helper_out_ops = {
+ .hook = ip_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+};
+
+static struct nf_hook_ops ip_conntrack_helper_in_ops = {
+ .hook = ip_conntrack_help,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_CONNTRACK_HELPER,
+};
+
/* Refragmenter; last chance. */
static struct nf_hook_ops ip_conntrack_out_ops = {
.hook = ip_refrag,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
- .priority = NF_IP_PRI_LAST,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
};
static struct nf_hook_ops ip_conntrack_local_in_ops = {
@@ -530,7 +555,7 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = {
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
- .priority = NF_IP_PRI_LAST-1,
+ .priority = NF_IP_PRI_CONNTRACK_CONFIRM,
};
/* Sysctl support */
@@ -831,10 +856,20 @@ static int init_or_cleanup(int init)
printk("ip_conntrack: can't register local out hook.\n");
goto cleanup_inops;
}
+ ret = nf_register_hook(&ip_conntrack_helper_in_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register local in helper hook.\n");
+ goto cleanup_inandlocalops;
+ }
+ ret = nf_register_hook(&ip_conntrack_helper_out_ops);
+ if (ret < 0) {
+ printk("ip_conntrack: can't register postrouting helper hook.\n");
+ goto cleanup_helperinops;
+ }
ret = nf_register_hook(&ip_conntrack_out_ops);
if (ret < 0) {
printk("ip_conntrack: can't register post-routing hook.\n");
- goto cleanup_inandlocalops;
+ goto cleanup_helperoutops;
}
ret = nf_register_hook(&ip_conntrack_local_in_ops);
if (ret < 0) {
@@ -860,6 +895,10 @@ static int init_or_cleanup(int init)
nf_unregister_hook(&ip_conntrack_local_in_ops);
cleanup_inoutandlocalops:
nf_unregister_hook(&ip_conntrack_out_ops);
+ cleanup_helperoutops:
+ nf_unregister_hook(&ip_conntrack_helper_out_ops);
+ cleanup_helperinops:
+ nf_unregister_hook(&ip_conntrack_helper_in_ops);
cleanup_inandlocalops:
nf_unregister_hook(&ip_conntrack_local_out_ops);
cleanup_inops:
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 162ceacfc29..9fc6f93af0d 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -356,15 +356,6 @@ unsigned int nat_packet(struct ip_conntrack *ct,
unsigned long statusbit;
enum ip_nat_manip_type mtype = HOOK2MANIP(hooknum);
- if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)
- && (hooknum == NF_IP_POST_ROUTING || hooknum == NF_IP_LOCAL_IN)) {
- DEBUGP("ip_nat_core: adjusting sequence number\n");
- /* future: put this in a l4-proto specific function,
- * and call this function here. */
- if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
- return NF_DROP;
- }
-
if (mtype == IP_NAT_MANIP_SRC)
statusbit = IPS_SRC_NAT;
else
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index dec4a74212c..79f56f662b3 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -230,6 +230,25 @@ ip_nat_local_fn(unsigned int hooknum,
return ret;
}
+static unsigned int
+ip_nat_adjust(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = ip_conntrack_get(*pskb, &ctinfo);
+ if (ct && test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
+ DEBUGP("ip_nat_standalone: adjusting sequence number\n");
+ if (!ip_nat_seq_adjust(pskb, ct, ctinfo))
+ return NF_DROP;
+ }
+ return NF_ACCEPT;
+}
+
/* We must be after connection tracking and before packet filtering. */
/* Before packet filtering, change destination */
@@ -250,6 +269,15 @@ static struct nf_hook_ops ip_nat_out_ops = {
.priority = NF_IP_PRI_NAT_SRC,
};
+/* After conntrack, adjust sequence number */
+static struct nf_hook_ops ip_nat_adjust_out_ops = {
+ .hook = ip_nat_adjust,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_POST_ROUTING,
+ .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+};
+
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_local_out_ops = {
.hook = ip_nat_local_fn,
@@ -268,6 +296,16 @@ static struct nf_hook_ops ip_nat_local_in_ops = {
.priority = NF_IP_PRI_NAT_SRC,
};
+/* After conntrack, adjust sequence number */
+static struct nf_hook_ops ip_nat_adjust_in_ops = {
+ .hook = ip_nat_adjust,
+ .owner = THIS_MODULE,
+ .pf = PF_INET,
+ .hooknum = NF_IP_LOCAL_IN,
+ .priority = NF_IP_PRI_NAT_SEQ_ADJUST,
+};
+
+
static int init_or_cleanup(int init)
{
int ret = 0;
@@ -296,10 +334,20 @@ static int init_or_cleanup(int init)
printk("ip_nat_init: can't register out hook.\n");
goto cleanup_inops;
}
+ ret = nf_register_hook(&ip_nat_adjust_in_ops);
+ if (ret < 0) {
+ printk("ip_nat_init: can't register adjust in hook.\n");
+ goto cleanup_outops;
+ }
+ ret = nf_register_hook(&ip_nat_adjust_out_ops);
+ if (ret < 0) {
+ printk("ip_nat_init: can't register adjust out hook.\n");
+ goto cleanup_adjustin_ops;
+ }
ret = nf_register_hook(&ip_nat_local_out_ops);
if (ret < 0) {
printk("ip_nat_init: can't register local out hook.\n");
- goto cleanup_outops;
+ goto cleanup_adjustout_ops;;
}
ret = nf_register_hook(&ip_nat_local_in_ops);
if (ret < 0) {
@@ -312,6 +360,10 @@ static int init_or_cleanup(int init)
nf_unregister_hook(&ip_nat_local_in_ops);
cleanup_localoutops:
nf_unregister_hook(&ip_nat_local_out_ops);
+ cleanup_adjustout_ops:
+ nf_unregister_hook(&ip_nat_adjust_out_ops);
+ cleanup_adjustin_ops:
+ nf_unregister_hook(&ip_nat_adjust_in_ops);
cleanup_outops:
nf_unregister_hook(&ip_nat_out_ops);
cleanup_inops:
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 13c14cb6dee..a12df6979ff 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -427,7 +427,7 @@ void tcp_push_one(struct sock *sk, unsigned cur_mss)
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb = sk->sk_send_head;
- if (tcp_snd_test(tp, skb, cur_mss, TCP_NAGLE_PUSH)) {
+ if (tcp_snd_test(sk, skb, cur_mss, TCP_NAGLE_PUSH)) {
/* Send it out now. */
TCP_SKB_CB(skb)->when = tcp_time_stamp;
tcp_tso_set_push(skb);
@@ -440,9 +440,12 @@ void tcp_push_one(struct sock *sk, unsigned cur_mss)
}
}
-void tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_std)
+void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb)
{
- if (skb->len <= mss_std) {
+ struct tcp_sock *tp = tcp_sk(sk);
+
+ if (skb->len <= tp->mss_cache_std ||
+ !(sk->sk_route_caps & NETIF_F_TSO)) {
/* Avoid the costly divide in the normal
* non-TSO case.
*/
@@ -451,10 +454,10 @@ void tcp_set_skb_tso_segs(struct sk_buff *skb, unsigned int mss_std)
} else {
unsigned int factor;
- factor = skb->len + (mss_std - 1);
- factor /= mss_std;
+ factor = skb->len + (tp->mss_cache_std - 1);
+ factor /= tp->mss_cache_std;
skb_shinfo(skb)->tso_segs = factor;
- skb_shinfo(skb)->tso_size = mss_std;
+ skb_shinfo(skb)->tso_size = tp->mss_cache_std;
}
}
@@ -525,8 +528,8 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
}
/* Fix up tso_factor for both original and new SKB. */
- tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
- tcp_set_skb_tso_segs(buff, tp->mss_cache_std);
+ tcp_set_skb_tso_segs(sk, skb);
+ tcp_set_skb_tso_segs(sk, buff);
if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
tp->lost_out += tcp_skb_pcount(skb);
@@ -601,7 +604,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
* factor and mss.
*/
if (tcp_skb_pcount(skb) > 1)
- tcp_set_skb_tso_segs(skb, tcp_skb_mss(skb));
+ tcp_set_skb_tso_segs(sk, skb);
return 0;
}
@@ -752,7 +755,7 @@ int tcp_write_xmit(struct sock *sk, int nonagle)
mss_now = tcp_current_mss(sk, 1);
while ((skb = sk->sk_send_head) &&
- tcp_snd_test(tp, skb, mss_now,
+ tcp_snd_test(sk, skb, mss_now,
tcp_skb_is_last(sk, skb) ? nonagle :
TCP_NAGLE_PUSH)) {
if (skb->len > mss_now) {
@@ -1676,7 +1679,7 @@ int tcp_write_wakeup(struct sock *sk)
tp->mss_cache = tp->mss_cache_std;
}
} else if (!tcp_skb_pcount(skb))
- tcp_set_skb_tso_segs(skb, tp->mss_cache_std);
+ tcp_set_skb_tso_segs(sk, skb);
TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
TCP_SKB_CB(skb)->when = tcp_time_stamp;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 768b11703da..53a6680d540 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -88,6 +88,7 @@ int sysctl_ipv6_bindv6only;
#ifdef INET_REFCNT_DEBUG
atomic_t inet6_sock_nr;
+EXPORT_SYMBOL(inet6_sock_nr);
#endif
/* The inetsw table contains everything that inet_create needs to
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index 6dda815c013..315bc1fbec3 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -41,8 +41,8 @@ int ipv6_ext_hdr(u8 nexthdr)
* when Linux implements ESP (and maybe AUTH) headers.
* --AK
*
- * This function parses (probably truncated) exthdr set "hdr"
- * of length "len". "nexthdrp" initially points to some place,
+ * This function parses (probably truncated) exthdr set "hdr".
+ * "nexthdrp" initially points to some place,
* where type of the first header can be found.
*
* It skips all well-known exthdrs, and returns pointer to the start
@@ -63,7 +63,7 @@ int ipv6_ext_hdr(u8 nexthdr)
* --ANK (980726)
*/
-int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len)
+int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp)
{
u8 nexthdr = *nexthdrp;
@@ -71,13 +71,11 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len
struct ipv6_opt_hdr _hdr, *hp;
int hdrlen;
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return -1;
if (nexthdr == NEXTHDR_NONE)
return -1;
hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
if (hp == NULL)
- BUG();
+ return -1;
if (nexthdr == NEXTHDR_FRAGMENT) {
unsigned short _frag_off, *fp;
fp = skb_header_pointer(skb,
@@ -97,7 +95,6 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp, int len
hdrlen = ipv6_optlen(hp);
nexthdr = hp->nexthdr;
- len -= hdrlen;
start += hdrlen;
}
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 87b9082ceab..8e0f569b883 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -135,7 +135,7 @@ static int is_ineligible(struct sk_buff *skb)
if (len < 0)
return 1;
- ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, len);
+ ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr);
if (ptr < 0)
return 0;
if (nexthdr == IPPROTO_ICMPV6) {
@@ -514,7 +514,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
if (ipv6_ext_hdr(nexthdr)) {
/* now skip over extension headers */
- inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, skb->len - sizeof(struct ipv6hdr));
+ inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
if (inner_offset<0)
return;
} else {
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 3d1d902dd1a..9c118baed9d 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -506,3 +506,13 @@ config NET_CLS_POLICE
Say Y to support traffic policing (bandwidth limits). Needed for
ingress and egress rate limiting.
+config NET_ACT_SIMP
+ tristate "Simple action"
+ depends on NET_CLS_ACT
+ ---help---
+ You must have new iproute2 to use this feature.
+ This adds a very simple action for demonstration purposes
+ The idea is to give action authors a basic example to look at.
+ All this action will do is print on the console the configured
+ policy string followed by _ then packet count.
+
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 431e55786ef..eb3fe583eba 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -6,13 +6,14 @@ obj-y := sch_generic.o
obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o
obj-$(CONFIG_NET_CLS) += cls_api.o
-obj-$(CONFIG_NET_CLS_ACT) += act_api.o
+obj-$(CONFIG_NET_CLS_ACT) += act_api.o
obj-$(CONFIG_NET_ACT_POLICE) += police.o
obj-$(CONFIG_NET_CLS_POLICE) += police.o
-obj-$(CONFIG_NET_ACT_GACT) += gact.o
-obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o
-obj-$(CONFIG_NET_ACT_IPT) += ipt.o
-obj-$(CONFIG_NET_ACT_PEDIT) += pedit.o
+obj-$(CONFIG_NET_ACT_GACT) += gact.o
+obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o
+obj-$(CONFIG_NET_ACT_IPT) += ipt.o
+obj-$(CONFIG_NET_ACT_PEDIT) += pedit.o
+obj-$(CONFIG_NET_ACT_SIMP) += simple.o
obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o
obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o
obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index fdfc83af3d1..29d8b9a4d16 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -46,9 +46,11 @@
#include <net/act_api.h>
#include <net/pkt_cls.h>
+#define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *))
+
struct fw_head
{
- struct fw_filter *ht[256];
+ struct fw_filter *ht[HTSIZE];
};
struct fw_filter
@@ -69,7 +71,28 @@ static struct tcf_ext_map fw_ext_map = {
static __inline__ int fw_hash(u32 handle)
{
- return handle&0xFF;
+ if (HTSIZE == 4096)
+ return ((handle >> 24) & 0xFFF) ^
+ ((handle >> 12) & 0xFFF) ^
+ (handle & 0xFFF);
+ else if (HTSIZE == 2048)
+ return ((handle >> 22) & 0x7FF) ^
+ ((handle >> 11) & 0x7FF) ^
+ (handle & 0x7FF);
+ else if (HTSIZE == 1024)
+ return ((handle >> 20) & 0x3FF) ^
+ ((handle >> 10) & 0x3FF) ^
+ (handle & 0x3FF);
+ else if (HTSIZE == 512)
+ return (handle >> 27) ^
+ ((handle >> 18) & 0x1FF) ^
+ ((handle >> 9) & 0x1FF) ^
+ (handle & 0x1FF);
+ else if (HTSIZE == 256) {
+ u8 *t = (u8 *) &handle;
+ return t[0] ^ t[1] ^ t[2] ^ t[3];
+ } else
+ return handle & (HTSIZE - 1);
}
static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
@@ -152,7 +175,7 @@ static void fw_destroy(struct tcf_proto *tp)
if (head == NULL)
return;
- for (h=0; h<256; h++) {
+ for (h=0; h<HTSIZE; h++) {
while ((f=head->ht[h]) != NULL) {
head->ht[h] = f->next;
fw_delete_filter(tp, f);
@@ -291,7 +314,7 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
if (arg->stop)
return;
- for (h = 0; h < 256; h++) {
+ for (h = 0; h < HTSIZE; h++) {
struct fw_filter *f;
for (f = head->ht[h]; f; f = f->next) {
diff --git a/net/sched/simple.c b/net/sched/simple.c
new file mode 100644
index 00000000000..b0d3d15848a
--- /dev/null
+++ b/net/sched/simple.c
@@ -0,0 +1,107 @@
+/*
+ * net/sched/simp.c Simple example of an action
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Jamal Hadi Salim (2005)
+ *
+ */
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+
+#define TCA_ACT_SIMP 22
+
+/* XXX: Hide all these common elements under some macro
+ * probably
+*/
+#include <linux/tc_act/tc_defact.h>
+#include <net/tc_act/tc_defact.h>
+
+/* use generic hash table with 8 buckets */
+#define MY_TAB_SIZE 8
+#define MY_TAB_MASK (MY_TAB_SIZE - 1)
+static u32 idx_gen;
+static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE];
+static DEFINE_RWLOCK(simp_lock);
+
+/* override the defaults */
+#define tcf_st tcf_defact
+#define tc_st tc_defact
+#define tcf_t_lock simp_lock
+#define tcf_ht tcf_simp_ht
+
+#define CONFIG_NET_ACT_INIT 1
+#include <net/pkt_act.h>
+#include <net/act_generic.h>
+
+static int tcf_simp(struct sk_buff **pskb, struct tc_action *a)
+{
+ struct sk_buff *skb = *pskb;
+ struct tcf_defact *p = PRIV(a, defact);
+
+ spin_lock(&p->lock);
+ p->tm.lastuse = jiffies;
+ p->bstats.bytes += skb->len;
+ p->bstats.packets++;
+
+ /* print policy string followed by _ then packet count
+ * Example if this was the 3rd packet and the string was "hello"
+ * then it would look like "hello_3" (without quotes)
+ **/
+ printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets);
+ spin_unlock(&p->lock);
+ return p->action;
+}
+
+static struct tc_action_ops act_simp_ops = {
+ .kind = "simple",
+ .type = TCA_ACT_SIMP,
+ .capab = TCA_CAP_NONE,
+ .owner = THIS_MODULE,
+ .act = tcf_simp,
+ tca_use_default_ops
+};
+
+MODULE_AUTHOR("Jamal Hadi Salim(2005)");
+MODULE_DESCRIPTION("Simple example action");
+MODULE_LICENSE("GPL");
+
+static int __init simp_init_module(void)
+{
+ int ret = tcf_register_action(&act_simp_ops);
+ if (!ret)
+ printk("Simple TC action Loaded\n");
+ return ret;
+}
+
+static void __exit simp_cleanup_module(void)
+{
+ tcf_unregister_action(&act_simp_ops);
+}
+
+module_init(simp_init_module);
+module_exit(simp_cleanup_module);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2ae7d3cb8df..0d378141c95 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2855,8 +2855,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
nexthdr = ip6->nexthdr;
offset += sizeof(_ipv6h);
- offset = ipv6_skip_exthdr(skb, offset, &nexthdr,
- skb->tail - skb->head - offset);
+ offset = ipv6_skip_exthdr(skb, offset, &nexthdr);
if (offset < 0)
goto out;