Commit e71f7103 authored by David S. Miller's avatar David S. Miller

Merge nuts.davemloft.net:/disk1/BK/network-2.6

into nuts.davemloft.net:/disk1/BK/net-2.6
parents 99202312 bb9a9e6e
...@@ -110,8 +110,8 @@ ...@@ -110,8 +110,8 @@
#endif #endif
extern const struct atmdev_ops fore200e_ops; static const struct atmdev_ops fore200e_ops;
extern const struct fore200e_bus fore200e_bus[]; static const struct fore200e_bus fore200e_bus[];
static struct fore200e* fore200e_boards = NULL; static struct fore200e* fore200e_boards = NULL;
......
...@@ -68,8 +68,6 @@ ...@@ -68,8 +68,6 @@
#define IF_IADBG_SUNI_STAT 0x02000000 // suni statistics #define IF_IADBG_SUNI_STAT 0x02000000 // suni statistics
#define IF_IADBG_RESET 0x04000000 #define IF_IADBG_RESET 0x04000000
extern unsigned int IADebugFlag;
#define IF_IADBG(f) if (IADebugFlag & (f)) #define IF_IADBG(f) if (IADebugFlag & (f))
#ifdef CONFIG_ATM_IA_DEBUG /* Debug build */ #ifdef CONFIG_ATM_IA_DEBUG /* Debug build */
......
...@@ -79,6 +79,8 @@ ...@@ -79,6 +79,8 @@
#define PPPOE_HASH_BITS 4 #define PPPOE_HASH_BITS 4
#define PPPOE_HASH_SIZE (1<<PPPOE_HASH_BITS) #define PPPOE_HASH_SIZE (1<<PPPOE_HASH_BITS)
static struct ppp_channel_ops pppoe_chan_ops;
static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb); static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb); static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
......
...@@ -52,7 +52,6 @@ extern int arlan_debug; ...@@ -52,7 +52,6 @@ extern int arlan_debug;
extern int arlan_entry_debug; extern int arlan_entry_debug;
extern int arlan_exit_debug; extern int arlan_exit_debug;
extern int testMemory; extern int testMemory;
extern const char* arlan_version;
extern int arlan_command(struct net_device * dev, int command); extern int arlan_command(struct net_device * dev, int command);
#define SIDUNKNOWN -1 #define SIDUNKNOWN -1
......
...@@ -677,6 +677,24 @@ static inline void hlist_add_after(struct hlist_node *n, ...@@ -677,6 +677,24 @@ static inline void hlist_add_after(struct hlist_node *n,
pos && ({ n = pos->next; 1; }) && \ pos && ({ n = pos->next; 1; }) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = n) pos = n)
/**
* hlist_for_each_entry_rcu - iterate over rcu list of given type
* @pos: the type * to use as a loop counter.
* @pos: the &struct hlist_node to use as a loop counter.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*
* This list-traversal primitive may safely run concurrently with
* the _rcu list-mutation primitives such as hlist_add_rcu()
* as long as the traversal is guarded by rcu_read_lock().
*/
#define hlist_for_each_entry_rcu(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && ({ prefetch(pos->next); 1;}) && \
({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next, ({ smp_read_barrier_depends(); 0; }) )
#else #else
#warning "don't include kernel headers in userspace" #warning "don't include kernel headers in userspace"
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -117,8 +117,6 @@ enum ...@@ -117,8 +117,6 @@ enum
struct tc_police struct tc_police
{ {
__u32 index; __u32 index;
int refcnt;
int bindcnt;
int action; int action;
#define TC_POLICE_UNSPEC TC_ACT_UNSPEC #define TC_POLICE_UNSPEC TC_ACT_UNSPEC
#define TC_POLICE_OK TC_ACT_OK #define TC_POLICE_OK TC_ACT_OK
...@@ -131,6 +129,9 @@ struct tc_police ...@@ -131,6 +129,9 @@ struct tc_police
__u32 mtu; __u32 mtu;
struct tc_ratespec rate; struct tc_ratespec rate;
struct tc_ratespec peakrate; struct tc_ratespec peakrate;
int refcnt;
int bindcnt;
__u32 capab;
}; };
struct tcf_t struct tcf_t
...@@ -188,6 +189,7 @@ enum ...@@ -188,6 +189,7 @@ enum
TCA_U32_POLICE, TCA_U32_POLICE,
TCA_U32_ACT, TCA_U32_ACT,
TCA_U32_INDEV, TCA_U32_INDEV,
TCA_U32_PCNT,
__TCA_U32_MAX __TCA_U32_MAX
}; };
...@@ -199,7 +201,6 @@ struct tc_u32_key ...@@ -199,7 +201,6 @@ struct tc_u32_key
__u32 val; __u32 val;
int off; int off;
int offmask; int offmask;
__u32 kcnt;
}; };
struct tc_u32_sel struct tc_u32_sel
...@@ -215,10 +216,16 @@ struct tc_u32_sel ...@@ -215,10 +216,16 @@ struct tc_u32_sel
short hoff; short hoff;
__u32 hmask; __u32 hmask;
struct tc_u32_key keys[0]; struct tc_u32_key keys[0];
unsigned long rcnt;
unsigned long rhit;
}; };
#ifdef CONFIG_CLS_U32_PERF
struct tc_u32_pcnt
{
__u64 rcnt;
__u64 rhit;
__u64 kcnts[0];
};
#endif
/* Flags */ /* Flags */
#define TC_U32_TERMINAL 1 #define TC_U32_TERMINAL 1
...@@ -283,8 +290,8 @@ enum ...@@ -283,8 +290,8 @@ enum
TCA_FW_UNSPEC, TCA_FW_UNSPEC,
TCA_FW_CLASSID, TCA_FW_CLASSID,
TCA_FW_POLICE, TCA_FW_POLICE,
TCA_FW_INDEV, TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */
TCA_FW_ACT, TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
__TCA_FW_MAX __TCA_FW_MAX
}; };
......
...@@ -233,7 +233,7 @@ struct sk_buff { ...@@ -233,7 +233,7 @@ struct sk_buff {
* want to keep them across layers you have to do a skb_clone() * want to keep them across layers you have to do a skb_clone()
* first. This is owned by whoever has the skb queued ATM. * first. This is owned by whoever has the skb queued ATM.
*/ */
char cb[48]; char cb[40];
unsigned int len, unsigned int len,
data_len, data_len,
......
...@@ -210,6 +210,4 @@ static inline int irttp_is_primary(struct tsap_cb *self) ...@@ -210,6 +210,4 @@ static inline int irttp_is_primary(struct tsap_cb *self)
return(irlap_is_primary(self->lsap->lap->irlap)); return(irlap_is_primary(self->lsap->lap->irlap));
} }
extern struct irttp_cb *irttp;
#endif /* IRTTP_H */ #endif /* IRTTP_H */
...@@ -112,9 +112,6 @@ struct nr_node { ...@@ -112,9 +112,6 @@ struct nr_node {
* nr_node & nr_neigh lists, refcounting and locking * nr_node & nr_neigh lists, refcounting and locking
*********************************************************************/ *********************************************************************/
extern struct hlist_head nr_node_list;
extern struct hlist_head nr_neigh_list;
#define nr_node_hold(__nr_node) \ #define nr_node_hold(__nr_node) \
atomic_inc(&((__nr_node)->refcount)) atomic_inc(&((__nr_node)->refcount))
......
...@@ -829,6 +829,7 @@ extern int xfrm6_tunnel_check_size(struct sk_buff *skb); ...@@ -829,6 +829,7 @@ extern int xfrm6_tunnel_check_size(struct sk_buff *skb);
extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
extern int xfrm6_output(struct sk_buff **pskb);
#ifdef CONFIG_XFRM #ifdef CONFIG_XFRM
extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
......
...@@ -109,6 +109,8 @@ source "net/ipv4/Kconfig" ...@@ -109,6 +109,8 @@ source "net/ipv4/Kconfig"
config IPV6 config IPV6
tristate "The IPv6 protocol (EXPERIMENTAL)" tristate "The IPv6 protocol (EXPERIMENTAL)"
depends on INET && EXPERIMENTAL depends on INET && EXPERIMENTAL
select CRYPTO if IPV6_PRIVACY
select CRYPTO_MD5 if IPV6_PRIVACY
---help--- ---help---
This is experimental support for the IP version 6 (formerly called This is experimental support for the IP version 6 (formerly called
IPng "IP next generation"). You will still be able to do IPng "IP next generation"). You will still be able to do
......
...@@ -28,43 +28,28 @@ static struct net_device_stats *br_dev_get_stats(struct net_device *dev) ...@@ -28,43 +28,28 @@ static struct net_device_stats *br_dev_get_stats(struct net_device *dev)
return &br->statistics; return &br->statistics;
} }
static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev) int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct net_bridge *br; struct net_bridge *br = netdev_priv(dev);
unsigned char *dest; const unsigned char *dest = skb->data;
struct net_bridge_fdb_entry *dst; struct net_bridge_fdb_entry *dst;
br = dev->priv;
br->statistics.tx_packets++; br->statistics.tx_packets++;
br->statistics.tx_bytes += skb->len; br->statistics.tx_bytes += skb->len;
dest = skb->mac.raw = skb->data; skb->mac.raw = skb->data;
skb_pull(skb, ETH_HLEN); skb_pull(skb, ETH_HLEN);
if (dest[0] & 1) { rcu_read_lock();
if (dest[0] & 1)
br_flood_deliver(br, skb, 0); br_flood_deliver(br, skb, 0);
return 0; else if ((dst = __br_fdb_get(br, dest)) != NULL)
}
if ((dst = br_fdb_get(br, dest)) != NULL) {
br_deliver(dst->dst, skb); br_deliver(dst->dst, skb);
br_fdb_put(dst); else
return 0; br_flood_deliver(br, skb, 0);
}
br_flood_deliver(br, skb, 0);
return 0;
}
int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
{
int ret;
rcu_read_lock();
ret = __br_dev_xmit(skb, dev);
rcu_read_unlock(); rcu_read_unlock();
return 0;
return ret;
} }
static int br_dev_open(struct net_device *dev) static int br_dev_open(struct net_device *dev)
......
...@@ -73,7 +73,7 @@ static __inline__ int br_mac_hash(const unsigned char *mac) ...@@ -73,7 +73,7 @@ static __inline__ int br_mac_hash(const unsigned char *mac)
static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f) static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f)
{ {
hlist_del(&f->hlist); hlist_del_rcu(&f->hlist);
if (!f->is_static) if (!f->is_static)
list_del(&f->age_list); list_del(&f->age_list);
...@@ -85,7 +85,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) ...@@ -85,7 +85,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
struct net_bridge *br = p->br; struct net_bridge *br = p->br;
int i; int i;
write_lock_bh(&br->hash_lock); spin_lock_bh(&br->hash_lock);
/* Search all chains since old address/hash is unknown */ /* Search all chains since old address/hash is unknown */
for (i = 0; i < BR_HASH_SIZE; i++) { for (i = 0; i < BR_HASH_SIZE; i++) {
...@@ -117,7 +117,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) ...@@ -117,7 +117,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
fdb_insert(br, p, newaddr, 1); fdb_insert(br, p, newaddr, 1);
write_unlock_bh(&br->hash_lock); spin_unlock_bh(&br->hash_lock);
} }
void br_fdb_cleanup(unsigned long _data) void br_fdb_cleanup(unsigned long _data)
...@@ -126,7 +126,7 @@ void br_fdb_cleanup(unsigned long _data) ...@@ -126,7 +126,7 @@ void br_fdb_cleanup(unsigned long _data)
struct list_head *l, *n; struct list_head *l, *n;
unsigned long delay; unsigned long delay;
write_lock_bh(&br->hash_lock); spin_lock_bh(&br->hash_lock);
delay = hold_time(br); delay = hold_time(br);
list_for_each_safe(l, n, &br->age_list) { list_for_each_safe(l, n, &br->age_list) {
...@@ -144,14 +144,14 @@ void br_fdb_cleanup(unsigned long _data) ...@@ -144,14 +144,14 @@ void br_fdb_cleanup(unsigned long _data)
break; break;
} }
} }
write_unlock_bh(&br->hash_lock); spin_unlock_bh(&br->hash_lock);
} }
void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p) void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
{ {
int i; int i;
write_lock_bh(&br->hash_lock); spin_lock_bh(&br->hash_lock);
for (i = 0; i < BR_HASH_SIZE; i++) { for (i = 0; i < BR_HASH_SIZE; i++) {
struct hlist_node *h, *g; struct hlist_node *h, *g;
...@@ -182,37 +182,53 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p) ...@@ -182,37 +182,53 @@ void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
skip_delete: ; skip_delete: ;
} }
} }
write_unlock_bh(&br->hash_lock); spin_unlock_bh(&br->hash_lock);
} }
struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, unsigned char *addr) /* No locking or refcounting, assumes caller has no preempt (rcu_read_lock) */
struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
const unsigned char *addr)
{ {
struct hlist_node *h; struct hlist_node *h;
struct net_bridge_fdb_entry *fdb;
read_lock_bh(&br->hash_lock); hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) {
hlist_for_each(h, &br->hash[br_mac_hash(addr)]) {
struct net_bridge_fdb_entry *fdb
= hlist_entry(h, struct net_bridge_fdb_entry, hlist);
if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) { if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
if (has_expired(br, fdb)) if (unlikely(has_expired(br, fdb)))
goto ret_null; break;
atomic_inc(&fdb->use_count);
read_unlock_bh(&br->hash_lock);
return fdb; return fdb;
} }
} }
ret_null:
read_unlock_bh(&br->hash_lock);
return NULL; return NULL;
} }
/* Interface used by ATM hook that keeps a ref count */
struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
unsigned char *addr)
{
struct net_bridge_fdb_entry *fdb;
rcu_read_lock();
fdb = __br_fdb_get(br, addr);
if (fdb)
atomic_inc(&fdb->use_count);
rcu_read_unlock();
return fdb;
}
static void fdb_rcu_free(struct rcu_head *head)
{
struct net_bridge_fdb_entry *ent
= container_of(head, struct net_bridge_fdb_entry, rcu);
kmem_cache_free(br_fdb_cache, ent);
}
/* Set entry up for deletion with RCU */
void br_fdb_put(struct net_bridge_fdb_entry *ent) void br_fdb_put(struct net_bridge_fdb_entry *ent)
{ {
if (atomic_dec_and_test(&ent->use_count)) if (atomic_dec_and_test(&ent->use_count))
kmem_cache_free(br_fdb_cache, ent); call_rcu(&ent->rcu, fdb_rcu_free);
} }
/* /*
...@@ -229,9 +245,9 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, ...@@ -229,9 +245,9 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf,
memset(buf, 0, maxnum*sizeof(struct __fdb_entry)); memset(buf, 0, maxnum*sizeof(struct __fdb_entry));
read_lock_bh(&br->hash_lock); rcu_read_lock();
for (i = 0; i < BR_HASH_SIZE; i++) { for (i = 0; i < BR_HASH_SIZE; i++) {
hlist_for_each_entry(f, h, &br->hash[i], hlist) { hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) {
if (num >= maxnum) if (num >= maxnum)
goto out; goto out;
...@@ -255,7 +271,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, ...@@ -255,7 +271,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf,
} }
out: out:
read_unlock_bh(&br->hash_lock); rcu_read_unlock();
return num; return num;
} }
...@@ -309,7 +325,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, ...@@ -309,7 +325,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
memcpy(fdb->addr.addr, addr, ETH_ALEN); memcpy(fdb->addr.addr, addr, ETH_ALEN);
atomic_set(&fdb->use_count, 1); atomic_set(&fdb->use_count, 1);
hlist_add_head(&fdb->hlist, &br->hash[hash]); hlist_add_head_rcu(&fdb->hlist, &br->hash[hash]);
if (!timer_pending(&br->gc_timer)) { if (!timer_pending(&br->gc_timer)) {
br->gc_timer.expires = jiffies + hold_time(br); br->gc_timer.expires = jiffies + hold_time(br);
...@@ -332,8 +348,8 @@ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, ...@@ -332,8 +348,8 @@ int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
{ {
int ret; int ret;
write_lock_bh(&br->hash_lock); spin_lock_bh(&br->hash_lock);
ret = fdb_insert(br, source, addr, is_local); ret = fdb_insert(br, source, addr, is_local);
write_unlock_bh(&br->hash_lock); spin_unlock_bh(&br->hash_lock);
return ret; return ret;
} }
...@@ -149,7 +149,7 @@ static struct net_device *new_bridge_dev(const char *name) ...@@ -149,7 +149,7 @@ static struct net_device *new_bridge_dev(const char *name)
br->lock = SPIN_LOCK_UNLOCKED; br->lock = SPIN_LOCK_UNLOCKED;
INIT_LIST_HEAD(&br->port_list); INIT_LIST_HEAD(&br->port_list);
br->hash_lock = RW_LOCK_UNLOCKED; br->hash_lock = SPIN_LOCK_UNLOCKED;
br->bridge_id.prio[0] = 0x80; br->bridge_id.prio[0] = 0x80;
br->bridge_id.prio[1] = 0x00; br->bridge_id.prio[1] = 0x00;
...@@ -295,6 +295,7 @@ int br_del_bridge(const char *name) ...@@ -295,6 +295,7 @@ int br_del_bridge(const char *name)
return ret; return ret;
} }
/* Mtu of the bridge pseudo-device 1500 or the minimum of the ports */
int br_min_mtu(const struct net_bridge *br) int br_min_mtu(const struct net_bridge *br)
{ {
const struct net_bridge_port *p; const struct net_bridge_port *p;
...@@ -343,11 +344,12 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) ...@@ -343,11 +344,12 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br_stp_recalculate_bridge_id(br); br_stp_recalculate_bridge_id(br);
if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP)) if ((br->dev->flags & IFF_UP)
&& (dev->flags & IFF_UP) && netif_carrier_ok(dev))
br_stp_enable_port(p); br_stp_enable_port(p);
spin_unlock_bh(&br->lock); spin_unlock_bh(&br->lock);
br->dev->mtu = br_min_mtu(br); dev_set_mtu(br->dev, br_min_mtu(br));
} }
return err; return err;
......
...@@ -83,19 +83,17 @@ int br_handle_frame_finish(struct sk_buff *skb) ...@@ -83,19 +83,17 @@ int br_handle_frame_finish(struct sk_buff *skb)
goto out; goto out;
} }
dst = br_fdb_get(br, dest); dst = __br_fdb_get(br, dest);
if (dst != NULL && dst->is_local) { if (dst != NULL && dst->is_local) {
if (!passedup) if (!passedup)
br_pass_frame_up(br, skb); br_pass_frame_up(br, skb);
else else
kfree_skb(skb); kfree_skb(skb);
br_fdb_put(dst);
goto out; goto out;
} }
if (dst != NULL) { if (dst != NULL) {
br_forward(dst->dst, skb); br_forward(dst->dst, skb);
br_fdb_put(dst);
goto out; goto out;
} }
......
...@@ -19,58 +19,59 @@ ...@@ -19,58 +19,59 @@
static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr); static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr);
struct notifier_block br_device_notifier = struct notifier_block br_device_notifier = {
{
.notifier_call = br_device_event .notifier_call = br_device_event
}; };
static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
{ {
struct net_device *dev; struct net_device *dev = ptr;
struct net_bridge_port *p; struct net_bridge_port *p = dev->br_port;
struct net_bridge *br; struct net_bridge *br;
dev = ptr;
p = dev->br_port;
if (p == NULL) if (p == NULL)
return NOTIFY_DONE; return NOTIFY_DONE;
br = p->br; br = p->br;
if ( !(br->dev->flags & IFF_UP))
return NOTIFY_DONE;
if (event == NETDEV_CHANGEMTU) {
dev_set_mtu(br->dev, br_min_mtu(br));
return NOTIFY_DONE;
}
spin_lock_bh(&br->lock);
switch (event) { switch (event) {
case NETDEV_CHANGEADDR: case NETDEV_CHANGEADDR:
spin_lock_bh(&br->lock);
br_fdb_changeaddr(p, dev->dev_addr); br_fdb_changeaddr(p, dev->dev_addr);
if (br->dev->flags & IFF_UP) br_stp_recalculate_bridge_id(br);
br_stp_recalculate_bridge_id(br);
spin_unlock_bh(&br->lock);
break; break;
case NETDEV_CHANGEMTU: case NETDEV_CHANGE: /* device is up but carrier changed */
br->dev->mtu = br_min_mtu(br); if (netif_carrier_ok(dev)) {
if (p->state == BR_STATE_DISABLED)
br_stp_enable_port(p);
} else {
if (p->state != BR_STATE_DISABLED)
br_stp_disable_port(p);
}
break; break;
case NETDEV_DOWN: case NETDEV_DOWN:
if (br->dev->flags & IFF_UP) { br_stp_disable_port(p);
spin_lock_bh(&br->lock);
br_stp_disable_port(p);
spin_unlock_bh(&br->lock);
}
break; break;
case NETDEV_UP: case NETDEV_UP:
if (br->dev->flags & IFF_UP) { if (netif_carrier_ok(dev))
spin_lock_bh(&br->lock);
br_stp_enable_port(p); br_stp_enable_port(p);
spin_unlock_bh(&br->lock);
}
break; break;
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
br_del_if(br, dev); br_del_if(br, dev);
break; break;
} }
spin_unlock_bh(&br->lock);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -46,7 +46,10 @@ struct net_bridge_fdb_entry ...@@ -46,7 +46,10 @@ struct net_bridge_fdb_entry
{ {
struct hlist_node hlist; struct hlist_node hlist;
struct net_bridge_port *dst; struct net_bridge_port *dst;
struct list_head age_list; union {
struct list_head age_list;
struct rcu_head rcu;
};
atomic_t use_count; atomic_t use_count;
unsigned long ageing_timer; unsigned long ageing_timer;
mac_addr addr; mac_addr addr;
...@@ -86,7 +89,7 @@ struct net_bridge ...@@ -86,7 +89,7 @@ struct net_bridge
struct list_head port_list; struct list_head port_list;
struct net_device *dev; struct net_device *dev;
struct net_device_stats statistics; struct net_device_stats statistics;
rwlock_t hash_lock; spinlock_t hash_lock;
struct hlist_head hash[BR_HASH_SIZE]; struct hlist_head hash[BR_HASH_SIZE];
struct list_head age_list; struct list_head age_list;
...@@ -136,8 +139,10 @@ extern void br_fdb_changeaddr(struct net_bridge_port *p, ...@@ -136,8 +139,10 @@ extern void br_fdb_changeaddr(struct net_bridge_port *p,
extern void br_fdb_cleanup(unsigned long arg); extern void br_fdb_cleanup(unsigned long arg);
extern void br_fdb_delete_by_port(struct net_bridge *br, extern void br_fdb_delete_by_port(struct net_bridge *br,
struct net_bridge_port *p); struct net_bridge_port *p);
extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
const unsigned char *addr);
extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
unsigned char *addr); unsigned char *addr);
extern void br_fdb_put(struct net_bridge_fdb_entry *ent); extern void br_fdb_put(struct net_bridge_fdb_entry *ent);
extern int br_fdb_fillbuf(struct net_bridge *br, void *buf, extern int br_fdb_fillbuf(struct net_bridge *br, void *buf,
unsigned long count, unsigned long off); unsigned long count, unsigned long off);
......
...@@ -52,7 +52,7 @@ void br_stp_enable_bridge(struct net_bridge *br) ...@@ -52,7 +52,7 @@ void br_stp_enable_bridge(struct net_bridge *br)
br_config_bpdu_generation(br); br_config_bpdu_generation(br);
list_for_each_entry(p, &br->port_list, list) { list_for_each_entry(p, &br->port_list, list) {
if (p->dev->flags & IFF_UP) if ((p->dev->flags & IFF_UP) && netif_carrier_ok(p->dev))
br_stp_enable_port(p); br_stp_enable_port(p);
} }
......
...@@ -3431,6 +3431,8 @@ EXPORT_SYMBOL(dev_queue_xmit_nit); ...@@ -3431,6 +3431,8 @@ EXPORT_SYMBOL(dev_queue_xmit_nit);
EXPORT_SYMBOL(dev_remove_pack); EXPORT_SYMBOL(dev_remove_pack);
EXPORT_SYMBOL(dev_set_allmulti); EXPORT_SYMBOL(dev_set_allmulti);
EXPORT_SYMBOL(dev_set_promiscuity); EXPORT_SYMBOL(dev_set_promiscuity);
EXPORT_SYMBOL(dev_change_flags);
EXPORT_SYMBOL(dev_set_mtu);
EXPORT_SYMBOL(free_netdev); EXPORT_SYMBOL(free_netdev);
EXPORT_SYMBOL(netdev_boot_setup_check); EXPORT_SYMBOL(netdev_boot_setup_check);
EXPORT_SYMBOL(netdev_set_master); EXPORT_SYMBOL(netdev_set_master);
...@@ -3448,10 +3450,7 @@ EXPORT_SYMBOL(unregister_netdevice_notifier); ...@@ -3448,10 +3450,7 @@ EXPORT_SYMBOL(unregister_netdevice_notifier);
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
EXPORT_SYMBOL(br_handle_frame_hook); EXPORT_SYMBOL(br_handle_frame_hook);
#endif #endif
/* for 801q VLAN support */
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
EXPORT_SYMBOL(dev_change_flags);
#endif
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
EXPORT_SYMBOL(dev_load); EXPORT_SYMBOL(dev_load);
#endif #endif
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
config IPV6_PRIVACY config IPV6_PRIVACY
bool "IPv6: Privacy Extensions (RFC 3041) support" bool "IPv6: Privacy Extensions (RFC 3041) support"
depends on IPV6 depends on IPV6
select CRYPTO
select CRYPTO_MD5
---help--- ---help---
Privacy Extensions for Stateless Address Autoconfiguration in IPv6 Privacy Extensions for Stateless Address Autoconfiguration in IPv6
support. With this option, additional periodically-alter support. With this option, additional periodically-alter
......
...@@ -11,7 +11,7 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ ...@@ -11,7 +11,7 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \
ip6_flowlabel.o ipv6_syms.o ip6_flowlabel.o ipv6_syms.o
ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
xfrm6_tunnel.o xfrm6_tunnel.o xfrm6_output.o
ipv6-objs += $(ipv6-y) ipv6-objs += $(ipv6-y)
obj-$(CONFIG_INET6_AH) += ah6.o obj-$(CONFIG_INET6_AH) += ah6.o
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <net/ah.h> #include <net/ah.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/pfkeyv2.h> #include <linux/pfkeyv2.h>
#include <linux/string.h>
#include <net/icmp.h> #include <net/icmp.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/xfrm.h> #include <net/xfrm.h>
...@@ -74,6 +75,45 @@ static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr) ...@@ -74,6 +75,45 @@ static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
return 0; return 0;
} }
/**
* ipv6_rearrange_rthdr - rearrange IPv6 routing header
* @iph: IPv6 header
* @rthdr: routing header
*
* Rearrange the destination address in @iph and the addresses in @rthdr
* so that they appear in the order they will at the final destination.
* See Appendix A2 of RFC 2402 for details.
*/
static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)
{
int segments, segments_left;
struct in6_addr *addrs;
struct in6_addr final_addr;
segments_left = rthdr->segments_left;
if (segments_left == 0)
return;
rthdr->segments_left = 0;
/* The value of rthdr->hdrlen has been verified either by the system
* call if it is locally generated, or by ipv6_rthdr_rcv() for incoming
* packets. So we can assume that it is even and that segments is
* greater than or equal to segments_left.
*
* For the same reason we can assume that this option is of type 0.
*/
segments = rthdr->hdrlen >> 1;
addrs = ((struct rt0_hdr *)rthdr)->addr;
ipv6_addr_copy(&final_addr, addrs + segments - 1);
addrs += segments - segments_left;
memmove(addrs + 1, addrs, (segments_left - 1) * sizeof(*addrs));
ipv6_addr_copy(addrs, &iph->daddr);
ipv6_addr_copy(&iph->daddr, &final_addr);
}
static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len) static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len)
{ {
union { union {
...@@ -101,7 +141,7 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len) ...@@ -101,7 +141,7 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len)
break; break;
case NEXTHDR_ROUTING: case NEXTHDR_ROUTING:
exthdr.rth->segments_left = 0; ipv6_rearrange_rthdr(iph, exthdr.rth);
break; break;
default : default :
...@@ -118,70 +158,55 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len) ...@@ -118,70 +158,55 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len)
int ah6_output(struct sk_buff **pskb) int ah6_output(struct sk_buff **pskb)
{ {
int err; int err;
int hdr_len = sizeof(struct ipv6hdr); int extlen;
struct dst_entry *dst = (*pskb)->dst; struct dst_entry *dst = (*pskb)->dst;
struct xfrm_state *x = dst->xfrm; struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *iph = NULL; struct ipv6hdr *top_iph;
struct ip_auth_hdr *ah; struct ip_auth_hdr *ah;
struct ah_data *ahp; struct ah_data *ahp;
u8 nexthdr; u8 nexthdr;
char tmp_base[8];
struct {
struct in6_addr daddr;
char hdrs[0];
} *tmp_ext;
if ((*pskb)->ip_summed == CHECKSUM_HW) { top_iph = (struct ipv6hdr *)(*pskb)->data;
err = skb_checksum_help(pskb, 0); top_iph->payload_len = htons((*pskb)->len - sizeof(*top_iph));
if (err)
goto error_nolock;
}
spin_lock_bh(&x->lock); nexthdr = *(*pskb)->nh.raw;
err = xfrm_state_check(x, *pskb); *(*pskb)->nh.raw = IPPROTO_AH;
if (err)
goto error;
if (x->props.mode) { /* When there are no extension headers, we only need to save the first
err = xfrm6_tunnel_check_size(*pskb); * 8 bytes of the base IP header.
if (err) */
goto error; memcpy(tmp_base, top_iph, sizeof(tmp_base));
iph = (*pskb)->nh.ipv6h; tmp_ext = NULL;
(*pskb)->nh.ipv6h = (struct ipv6hdr*)skb_push(*pskb, x->props.header_len); extlen = (*pskb)->h.raw - (unsigned char *)(top_iph + 1);
(*pskb)->nh.ipv6h->version = 6; if (extlen) {
(*pskb)->nh.ipv6h->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); extlen += sizeof(*tmp_ext);
(*pskb)->nh.ipv6h->nexthdr = IPPROTO_AH; tmp_ext = kmalloc(extlen, GFP_ATOMIC);
ipv6_addr_copy(&(*pskb)->nh.ipv6h->saddr, if (!tmp_ext) {
(struct in6_addr *) &x->props.saddr);
ipv6_addr_copy(&(*pskb)->nh.ipv6h->daddr,
(struct in6_addr *) &x->id.daddr);
ah = (struct ip_auth_hdr*)((*pskb)->nh.ipv6h+1);
ah->nexthdr = IPPROTO_IPV6;
} else {
u8 *prevhdr;
hdr_len = ip6_find_1stfragopt(*pskb, &prevhdr);
nexthdr = *prevhdr;
*prevhdr = IPPROTO_AH;
iph = kmalloc(hdr_len, GFP_ATOMIC);
if (!iph) {
err = -ENOMEM; err = -ENOMEM;
goto error; goto error;
} }
memcpy(iph, (*pskb)->data, hdr_len); memcpy(tmp_ext, &top_iph->daddr, extlen);
(*pskb)->nh.ipv6h = (struct ipv6hdr*)skb_push(*pskb, x->props.header_len); err = ipv6_clear_mutable_options(top_iph,
iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); extlen - sizeof(*tmp_ext) +
memcpy((*pskb)->nh.ipv6h, iph, hdr_len); sizeof(*top_iph));
err = ipv6_clear_mutable_options((*pskb)->nh.ipv6h, hdr_len);
if (err) if (err)
goto error_free_iph; goto error_free_iph;
ah = (struct ip_auth_hdr*)((*pskb)->nh.raw+hdr_len);
(*pskb)->h.raw = (unsigned char*) ah;
ah->nexthdr = nexthdr;
} }
(*pskb)->nh.ipv6h->priority = 0; ah = (struct ip_auth_hdr *)(*pskb)->h.raw;
(*pskb)->nh.ipv6h->flow_lbl[0] = 0; ah->nexthdr = nexthdr;
(*pskb)->nh.ipv6h->flow_lbl[1] = 0;
(*pskb)->nh.ipv6h->flow_lbl[2] = 0; top_iph->priority = 0;
(*pskb)->nh.ipv6h->hop_limit = 0; top_iph->flow_lbl[0] = 0;
top_iph->flow_lbl[1] = 0;
top_iph->flow_lbl[2] = 0;
top_iph->hop_limit = 0;
ahp = x->data; ahp = x->data;
ah->hdrlen = (XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ah->hdrlen = (XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) +
...@@ -192,35 +217,16 @@ int ah6_output(struct sk_buff **pskb) ...@@ -192,35 +217,16 @@ int ah6_output(struct sk_buff **pskb)
ah->seq_no = htonl(++x->replay.oseq); ah->seq_no = htonl(++x->replay.oseq);
ahp->icv(ahp, *pskb, ah->auth_data); ahp->icv(ahp, *pskb, ah->auth_data);
if (x->props.mode) { err = 0;
(*pskb)->nh.ipv6h->hop_limit = iph->hop_limit;
(*pskb)->nh.ipv6h->priority = iph->priority;
(*pskb)->nh.ipv6h->flow_lbl[0] = iph->flow_lbl[0];
(*pskb)->nh.ipv6h->flow_lbl[1] = iph->flow_lbl[1];
(*pskb)->nh.ipv6h->flow_lbl[2] = iph->flow_lbl[2];
if (x->props.flags & XFRM_STATE_NOECN)
IP6_ECN_clear((*pskb)->nh.ipv6h);
} else {
memcpy((*pskb)->nh.ipv6h, iph, hdr_len);
kfree (iph);
}
(*pskb)->nh.raw = (*pskb)->data;
x->curlft.bytes += (*pskb)->len; memcpy(top_iph, tmp_base, sizeof(tmp_base));
x->curlft.packets++; if (tmp_ext) {
spin_unlock_bh(&x->lock); memcpy(&top_iph->daddr, tmp_ext, extlen);
if (((*pskb)->dst = dst_pop(dst)) == NULL) {
err = -EHOSTUNREACH;
goto error_nolock;
}
return NET_XMIT_BYPASS;
error_free_iph: error_free_iph:
kfree(iph); kfree(tmp_ext);
}
error: error:
spin_unlock_bh(&x->lock);
error_nolock:
kfree_skb(*pskb);
return err; return err;
} }
......
...@@ -41,10 +41,10 @@ ...@@ -41,10 +41,10 @@
int esp6_output(struct sk_buff **pskb) int esp6_output(struct sk_buff **pskb)
{ {
int err; int err;
int hdr_len = 0; int hdr_len;
struct dst_entry *dst = (*pskb)->dst; struct dst_entry *dst = (*pskb)->dst;
struct xfrm_state *x = dst->xfrm; struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *iph = NULL, *top_iph; struct ipv6hdr *top_iph;
struct ipv6_esp_hdr *esph; struct ipv6_esp_hdr *esph;
struct crypto_tfm *tfm; struct crypto_tfm *tfm;
struct esp_data *esp; struct esp_data *esp;
...@@ -53,37 +53,13 @@ int esp6_output(struct sk_buff **pskb) ...@@ -53,37 +53,13 @@ int esp6_output(struct sk_buff **pskb)
int clen; int clen;
int alen; int alen;
int nfrags; int nfrags;
u8 *prevhdr;
u8 nexthdr = 0;
if ((*pskb)->ip_summed == CHECKSUM_HW) { esp = x->data;
err = skb_checksum_help(pskb, 0); hdr_len = (*pskb)->h.raw - (*pskb)->data +
if (err) sizeof(*esph) + esp->conf.ivlen;
goto error_nolock;
}
spin_lock_bh(&x->lock); /* Strip IP+ESP header. */
err = xfrm_state_check(x, *pskb); __skb_pull(*pskb, hdr_len);
if (err)
goto error;
if (x->props.mode) {
err = xfrm6_tunnel_check_size(*pskb);
if (err)
goto error;
} else {
/* Strip IP header in transport mode. Save it. */
hdr_len = ip6_find_1stfragopt(*pskb, &prevhdr);
nexthdr = *prevhdr;
*prevhdr = IPPROTO_ESP;
iph = kmalloc(hdr_len, GFP_ATOMIC);
if (!iph) {
err = -ENOMEM;
goto error;
}
memcpy(iph, (*pskb)->nh.raw, hdr_len);
__skb_pull(*pskb, hdr_len);
}
/* Now skb is pure payload to encrypt */ /* Now skb is pure payload to encrypt */
err = -ENOMEM; err = -ENOMEM;
...@@ -91,7 +67,6 @@ int esp6_output(struct sk_buff **pskb) ...@@ -91,7 +67,6 @@ int esp6_output(struct sk_buff **pskb)
/* Round to block size */ /* Round to block size */
clen = (*pskb)->len; clen = (*pskb)->len;
esp = x->data;
alen = esp->auth.icv_trunc_len; alen = esp->auth.icv_trunc_len;
tfm = esp->conf.tfm; tfm = esp->conf.tfm;
blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3; blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3;
...@@ -100,7 +75,6 @@ int esp6_output(struct sk_buff **pskb) ...@@ -100,7 +75,6 @@ int esp6_output(struct sk_buff **pskb)
clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1); clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1);
if ((nfrags = skb_cow_data(*pskb, clen-(*pskb)->len+alen, &trailer)) < 0) { if ((nfrags = skb_cow_data(*pskb, clen-(*pskb)->len+alen, &trailer)) < 0) {
if (!x->props.mode && iph) kfree(iph);
goto error; goto error;
} }
...@@ -113,34 +87,11 @@ int esp6_output(struct sk_buff **pskb) ...@@ -113,34 +87,11 @@ int esp6_output(struct sk_buff **pskb)
*(u8*)(trailer->tail + clen-(*pskb)->len - 2) = (clen - (*pskb)->len)-2; *(u8*)(trailer->tail + clen-(*pskb)->len - 2) = (clen - (*pskb)->len)-2;
pskb_put(*pskb, trailer, clen - (*pskb)->len); pskb_put(*pskb, trailer, clen - (*pskb)->len);
if (x->props.mode) { top_iph = (struct ipv6hdr *)__skb_push(*pskb, hdr_len);
iph = (*pskb)->nh.ipv6h; esph = (struct ipv6_esp_hdr *)(*pskb)->h.raw;
top_iph = (struct ipv6hdr*)skb_push(*pskb, x->props.header_len); top_iph->payload_len = htons((*pskb)->len + alen - sizeof(*top_iph));
esph = (struct ipv6_esp_hdr*)(top_iph+1); *(u8*)(trailer->tail - 1) = *(*pskb)->nh.raw;
*(u8*)(trailer->tail - 1) = IPPROTO_IPV6; *(*pskb)->nh.raw = IPPROTO_ESP;
top_iph->version = 6;
top_iph->priority = iph->priority;
top_iph->flow_lbl[0] = iph->flow_lbl[0];
top_iph->flow_lbl[1] = iph->flow_lbl[1];
top_iph->flow_lbl[2] = iph->flow_lbl[2];
if (x->props.flags & XFRM_STATE_NOECN)
IP6_ECN_clear(top_iph);
top_iph->nexthdr = IPPROTO_ESP;
top_iph->payload_len = htons((*pskb)->len + alen - sizeof(struct ipv6hdr));
top_iph->hop_limit = iph->hop_limit;
ipv6_addr_copy(&top_iph->saddr,
(struct in6_addr *)&x->props.saddr);
ipv6_addr_copy(&top_iph->daddr,
(struct in6_addr *)&x->id.daddr);
} else {
esph = (struct ipv6_esp_hdr*)skb_push(*pskb, x->props.header_len);
(*pskb)->h.raw = (unsigned char*)esph;
top_iph = (struct ipv6hdr*)skb_push(*pskb, hdr_len);
memcpy(top_iph, iph, hdr_len);
kfree(iph);
top_iph->payload_len = htons((*pskb)->len + alen - sizeof(struct ipv6hdr));
*(u8*)(trailer->tail - 1) = nexthdr;
}
esph->spi = x->id.spi; esph->spi = x->id.spi;
esph->seq_no = htonl(++x->replay.oseq); esph->seq_no = htonl(++x->replay.oseq);
...@@ -173,21 +124,9 @@ int esp6_output(struct sk_buff **pskb) ...@@ -173,21 +124,9 @@ int esp6_output(struct sk_buff **pskb)
pskb_put(*pskb, trailer, alen); pskb_put(*pskb, trailer, alen);
} }
(*pskb)->nh.raw = (*pskb)->data; err = 0;
x->curlft.bytes += (*pskb)->len;
x->curlft.packets++;
spin_unlock_bh(&x->lock);
if (((*pskb)->dst = dst_pop(dst)) == NULL) {
err = -EHOSTUNREACH;
goto error_nolock;
}
return NET_XMIT_BYPASS;
error: error:
spin_unlock_bh(&x->lock);
error_nolock:
kfree_skb(*pskb);
return err; return err;
} }
......
...@@ -94,7 +94,7 @@ static __u32 rt_sernum; ...@@ -94,7 +94,7 @@ static __u32 rt_sernum;
static struct timer_list ip6_fib_timer = TIMER_INITIALIZER(fib6_run_gc, 0, 0); static struct timer_list ip6_fib_timer = TIMER_INITIALIZER(fib6_run_gc, 0, 0);
static struct fib6_walker_t fib6_walker_list = { struct fib6_walker_t fib6_walker_list = {
.prev = &fib6_walker_list, .prev = &fib6_walker_list,
.next = &fib6_walker_list, .next = &fib6_walker_list,
}; };
......
...@@ -120,52 +120,14 @@ static int ipcomp6_output(struct sk_buff **pskb) ...@@ -120,52 +120,14 @@ static int ipcomp6_output(struct sk_buff **pskb)
int err; int err;
struct dst_entry *dst = (*pskb)->dst; struct dst_entry *dst = (*pskb)->dst;
struct xfrm_state *x = dst->xfrm; struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *iph, *top_iph; struct ipv6hdr *top_iph;
int hdr_len = 0; int hdr_len;
struct ipv6_comp_hdr *ipch; struct ipv6_comp_hdr *ipch;
struct ipcomp_data *ipcd = x->data; struct ipcomp_data *ipcd = x->data;
u8 *prevhdr;
u8 nexthdr = 0;
int plen, dlen; int plen, dlen;
u8 *start, *scratch = ipcd->scratch; u8 *start, *scratch = ipcd->scratch;
if ((*pskb)->ip_summed == CHECKSUM_HW) { hdr_len = (*pskb)->h.raw - (*pskb)->data;
err = skb_checksum_help(pskb, 0);
if (err)
goto error_nolock;
}
spin_lock_bh(&x->lock);
err = xfrm_state_check(x, *pskb);
if (err)
goto error;
if (x->props.mode) {
err = xfrm6_tunnel_check_size(*pskb);
if (err)
goto error;
hdr_len = sizeof(struct ipv6hdr);
nexthdr = IPPROTO_IPV6;
iph = (*pskb)->nh.ipv6h;
top_iph = (struct ipv6hdr *)skb_push(*pskb, sizeof(struct ipv6hdr));
top_iph->version = 6;
top_iph->priority = iph->priority;
top_iph->flow_lbl[0] = iph->flow_lbl[0];
top_iph->flow_lbl[1] = iph->flow_lbl[1];
top_iph->flow_lbl[2] = iph->flow_lbl[2];
top_iph->nexthdr = IPPROTO_IPV6; /* initial */
top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr));
top_iph->hop_limit = iph->hop_limit;
memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr));
memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr));
(*pskb)->nh.raw = (*pskb)->data; /* == top_iph */
(*pskb)->h.raw = (*pskb)->nh.raw + hdr_len;
} else {
hdr_len = ip6_find_1stfragopt(*pskb, &prevhdr);
nexthdr = *prevhdr;
}
/* check whether datagram len is larger than threshold */ /* check whether datagram len is larger than threshold */
if (((*pskb)->len - hdr_len) < ipcd->threshold) { if (((*pskb)->len - hdr_len) < ipcd->threshold) {
...@@ -181,7 +143,7 @@ static int ipcomp6_output(struct sk_buff **pskb) ...@@ -181,7 +143,7 @@ static int ipcomp6_output(struct sk_buff **pskb)
/* compression */ /* compression */
plen = (*pskb)->len - hdr_len; plen = (*pskb)->len - hdr_len;
dlen = IPCOMP_SCRATCH_SIZE; dlen = IPCOMP_SCRATCH_SIZE;
start = (*pskb)->data + hdr_len; start = (*pskb)->h.raw;
err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen); err = crypto_comp_compress(ipcd->tfm, start, plen, scratch, &dlen);
if (err) { if (err) {
...@@ -194,39 +156,21 @@ static int ipcomp6_output(struct sk_buff **pskb) ...@@ -194,39 +156,21 @@ static int ipcomp6_output(struct sk_buff **pskb)
pskb_trim(*pskb, hdr_len + dlen + sizeof(struct ip_comp_hdr)); pskb_trim(*pskb, hdr_len + dlen + sizeof(struct ip_comp_hdr));
/* insert ipcomp header and replace datagram */ /* insert ipcomp header and replace datagram */
top_iph = (*pskb)->nh.ipv6h; top_iph = (struct ipv6hdr *)(*pskb)->data;
if (x->props.mode && (x->props.flags & XFRM_STATE_NOECN))
IP6_ECN_clear(top_iph);
top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr)); top_iph->payload_len = htons((*pskb)->len - sizeof(struct ipv6hdr));
(*pskb)->nh.raw = (*pskb)->data; /* top_iph */
ip6_find_1stfragopt(*pskb, &prevhdr);
*prevhdr = IPPROTO_COMP;
ipch = (struct ipv6_comp_hdr *)((unsigned char *)top_iph + hdr_len); ipch = (struct ipv6_comp_hdr *)start;
ipch->nexthdr = nexthdr; ipch->nexthdr = *(*pskb)->nh.raw;
ipch->flags = 0; ipch->flags = 0;
ipch->cpi = htons((u16 )ntohl(x->id.spi)); ipch->cpi = htons((u16 )ntohl(x->id.spi));
*(*pskb)->nh.raw = IPPROTO_COMP;
(*pskb)->h.raw = (unsigned char*)ipch;
out_ok: out_ok:
x->curlft.bytes += (*pskb)->len; err = 0;
x->curlft.packets++;
spin_unlock_bh(&x->lock);
if (((*pskb)->dst = dst_pop(dst)) == NULL) {
err = -EHOSTUNREACH;
goto error_nolock;
}
err = NET_XMIT_BYPASS;
out_exit:
return err;
error: error:
spin_unlock_bh(&x->lock); return err;
error_nolock:
kfree_skb(*pskb);
goto out_exit;
} }
static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
......
/*
* xfrm6_output.c - Common IPsec encapsulation code for IPv6.
* Copyright (C) 2002 USAGI/WIDE Project
* Copyright (c) 2004 Herbert Xu <herbert@gondor.apana.org.au>
*
* 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.
*/
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <net/inet_ecn.h>
#include <net/ipv6.h>
#include <net/xfrm.h>
/* Add encapsulation header.
*
* In transport mode, the IP header and mutable extension headers will be moved
* forward to make space for the encapsulation header.
*
* In tunnel mode, the top IP header will be constructed per RFC 2401.
* The following fields in it shall be filled in by x->type->output:
* payload_len
*
* On exit, skb->h will be set to the start of the encapsulation header to be
* filled in by x->type->output and skb->nh will be set to the nextheader field
* of the extension header directly preceding the encapsulation header, or in
* its absence, that of the top IP header. The value of skb->data will always
* point to the top IP header.
*/
static void xfrm6_encap(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *iph, *top_iph;
skb_push(skb, x->props.header_len);
iph = skb->nh.ipv6h;
if (!x->props.mode) {
u8 *prevhdr;
int hdr_len;
hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
skb->nh.raw = prevhdr - x->props.header_len;
skb->h.raw = skb->data + hdr_len;
memmove(skb->data, iph, hdr_len);
return;
}
skb->nh.raw = skb->data;
top_iph = skb->nh.ipv6h;
skb->nh.raw = &top_iph->nexthdr;
skb->h.ipv6h = top_iph + 1;
top_iph->version = 6;
top_iph->priority = iph->priority;
if (x->props.flags & XFRM_STATE_NOECN)
IP6_ECN_clear(top_iph);
top_iph->flow_lbl[0] = iph->flow_lbl[0];
top_iph->flow_lbl[1] = iph->flow_lbl[1];
top_iph->flow_lbl[2] = iph->flow_lbl[2];
top_iph->nexthdr = IPPROTO_IPV6;
top_iph->hop_limit = iph->hop_limit;
ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
}
int xfrm6_output(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
int err;
if (skb->ip_summed == CHECKSUM_HW) {
err = skb_checksum_help(pskb, 0);
skb = *pskb;
if (err)
goto error_nolock;
}
spin_lock_bh(&x->lock);
err = xfrm_state_check(x, skb);
if (err)
goto error;
if (x->props.mode) {
err = xfrm6_tunnel_check_size(skb);
if (err)
goto error;
}
xfrm6_encap(skb);
err = x->type->output(pskb);
skb = *pskb;
if (err)
goto error;
x->curlft.bytes += skb->len;
x->curlft.packets++;
spin_unlock_bh(&x->lock);
skb->nh.raw = skb->data;
if (!(skb->dst = dst_pop(dst))) {
err = -EHOSTUNREACH;
goto error_nolock;
}
err = NET_XMIT_BYPASS;
out_exit:
return err;
error:
spin_unlock_bh(&x->lock);
error_nolock:
kfree_skb(skb);
goto out_exit;
}
...@@ -157,7 +157,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int ...@@ -157,7 +157,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
/* Copy neighbour for reachability confirmation */ /* Copy neighbour for reachability confirmation */
dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour);
dst_prev->input = rt->u.dst.input; dst_prev->input = rt->u.dst.input;
dst_prev->output = dst_prev->xfrm->type->output; dst_prev->output = xfrm6_output;
/* Sheit... I remember I did this right. Apparently, /* Sheit... I remember I did this right. Apparently,
* it was magically lost, so this code needs audit */ * it was magically lost, so this code needs audit */
x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#include <linux/ipsec.h> #include <linux/ipsec.h>
#include <net/ipv6.h> #include <net/ipv6.h>
extern struct xfrm_state_afinfo xfrm6_state_afinfo; static struct xfrm_state_afinfo xfrm6_state_afinfo;
static void static void
__xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl,
......
...@@ -365,46 +365,12 @@ EXPORT_SYMBOL(xfrm6_tunnel_check_size); ...@@ -365,46 +365,12 @@ EXPORT_SYMBOL(xfrm6_tunnel_check_size);
static int xfrm6_tunnel_output(struct sk_buff **pskb) static int xfrm6_tunnel_output(struct sk_buff **pskb)
{ {
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
struct dst_entry *dst = skb->dst; struct ipv6hdr *top_iph;
struct xfrm_state *x = dst->xfrm;
struct ipv6hdr *iph, *top_iph;
int err;
if ((err = xfrm6_tunnel_check_size(skb)) != 0)
goto error_nolock;
iph = skb->nh.ipv6h;
top_iph = (struct ipv6hdr *)skb_push(skb, x->props.header_len);
top_iph->version = 6;
top_iph->priority = iph->priority;
top_iph->flow_lbl[0] = iph->flow_lbl[0];
top_iph->flow_lbl[1] = iph->flow_lbl[1];
top_iph->flow_lbl[2] = iph->flow_lbl[2];
top_iph->nexthdr = IPPROTO_IPV6;
top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
top_iph->hop_limit = iph->hop_limit;
memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct in6_addr));
memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct in6_addr));
skb->nh.raw = skb->data;
skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
x->curlft.bytes += skb->len;
x->curlft.packets++;
spin_unlock_bh(&x->lock);
if ((skb->dst = dst_pop(dst)) == NULL) { top_iph = (struct ipv6hdr *)skb->data;
kfree_skb(skb); top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
err = -EHOSTUNREACH;
goto error_nolock;
}
return NET_XMIT_BYPASS;
error_nolock: return 0;
kfree_skb(skb);
return err;
} }
static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) static int xfrm6_tunnel_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/socket.h> #include <linux/socket.h>
...@@ -1451,8 +1452,7 @@ static int __init nr_proto_init(void) ...@@ -1451,8 +1452,7 @@ static int __init nr_proto_init(void)
module_init(nr_proto_init); module_init(nr_proto_init);
module_param(nr_ndevs, int, 0);
MODULE_PARM(nr_ndevs, "i");
MODULE_PARM_DESC(nr_ndevs, "number of NET/ROM devices"); MODULE_PARM_DESC(nr_ndevs, "number of NET/ROM devices");
MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>"); MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -57,7 +58,7 @@ int sysctl_rose_link_fail_timeout = ROSE_DEFAULT_FAIL_TIMEOUT; ...@@ -57,7 +58,7 @@ int sysctl_rose_link_fail_timeout = ROSE_DEFAULT_FAIL_TIMEOUT;
int sysctl_rose_maximum_vcs = ROSE_DEFAULT_MAXVC; int sysctl_rose_maximum_vcs = ROSE_DEFAULT_MAXVC;
int sysctl_rose_window_size = ROSE_DEFAULT_WINDOW_SIZE; int sysctl_rose_window_size = ROSE_DEFAULT_WINDOW_SIZE;
HLIST_HEAD(rose_list); static HLIST_HEAD(rose_list);
spinlock_t rose_list_lock = SPIN_LOCK_UNLOCKED; spinlock_t rose_list_lock = SPIN_LOCK_UNLOCKED;
static struct proto_ops rose_proto_ops; static struct proto_ops rose_proto_ops;
...@@ -1550,7 +1551,7 @@ static int __init rose_proto_init(void) ...@@ -1550,7 +1551,7 @@ static int __init rose_proto_init(void)
} }
module_init(rose_proto_init); module_init(rose_proto_init);
MODULE_PARM(rose_ndevs, "i"); module_param(rose_ndevs, int, 0);
MODULE_PARM_DESC(rose_ndevs, "number of ROSE devices"); MODULE_PARM_DESC(rose_ndevs, "number of ROSE devices");
MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>"); MODULE_AUTHOR("Jonathan Naylor G4KLX <g4klx@g4klx.demon.co.uk>");
......
...@@ -64,17 +64,20 @@ struct tc_u_knode ...@@ -64,17 +64,20 @@ struct tc_u_knode
struct tc_u_hnode *ht_up; struct tc_u_hnode *ht_up;
#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_ACT
struct tc_action *action; struct tc_action *action;
#ifdef CONFIG_NET_CLS_IND
char indev[IFNAMSIZ];
#endif
#else #else
#ifdef CONFIG_NET_CLS_POLICE #ifdef CONFIG_NET_CLS_POLICE
struct tcf_police *police; struct tcf_police *police;
#endif #endif
#endif
#ifdef CONFIG_NET_CLS_IND
char indev[IFNAMSIZ];
#endif #endif
u8 fshift; u8 fshift;
struct tcf_result res; struct tcf_result res;
struct tc_u_hnode *ht_down; struct tc_u_hnode *ht_down;
#ifdef CONFIG_CLS_U32_PERF
struct tc_u32_pcnt *pf;
#endif
struct tc_u32_sel sel; struct tc_u32_sel sel;
}; };
...@@ -120,6 +123,9 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re ...@@ -120,6 +123,9 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
int sdepth = 0; int sdepth = 0;
int off2 = 0; int off2 = 0;
int sel = 0; int sel = 0;
#ifdef CONFIG_CLS_U32_PERF
int j;
#endif
int i; int i;
next_ht: next_ht:
...@@ -130,7 +136,8 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re ...@@ -130,7 +136,8 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
struct tc_u32_key *key = n->sel.keys; struct tc_u32_key *key = n->sel.keys;
#ifdef CONFIG_CLS_U32_PERF #ifdef CONFIG_CLS_U32_PERF
n->sel.rcnt +=1; n->pf->rcnt +=1;
j = 0;
#endif #endif
for (i = n->sel.nkeys; i>0; i--, key++) { for (i = n->sel.nkeys; i>0; i--, key++) {
...@@ -139,7 +146,8 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re ...@@ -139,7 +146,8 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
goto next_knode; goto next_knode;
} }
#ifdef CONFIG_CLS_U32_PERF #ifdef CONFIG_CLS_U32_PERF
key->kcnt +=1; n->pf->kcnts[j] +=1;
j++;
#endif #endif
} }
if (n->ht_down == NULL) { if (n->ht_down == NULL) {
...@@ -147,7 +155,6 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re ...@@ -147,7 +155,6 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
if (n->sel.flags&TC_U32_TERMINAL) { if (n->sel.flags&TC_U32_TERMINAL) {
*res = n->res; *res = n->res;
#ifdef CONFIG_NET_CLS_ACT
#ifdef CONFIG_NET_CLS_IND #ifdef CONFIG_NET_CLS_IND
/* yes, i know it sucks but the feature is /* yes, i know it sucks but the feature is
** optional dammit! - JHS */ ** optional dammit! - JHS */
...@@ -164,8 +171,9 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re ...@@ -164,8 +171,9 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
} }
#endif #endif
#ifdef CONFIG_CLS_U32_PERF #ifdef CONFIG_CLS_U32_PERF
n->sel.rhit +=1; n->pf->rhit +=1;
#endif #endif
#ifdef CONFIG_NET_CLS_ACT
if (n->action) { if (n->action) {
int pol_res = tcf_action_exec(skb, n->action); int pol_res = tcf_action_exec(skb, n->action);
if (skb->tc_classid > 0) { if (skb->tc_classid > 0) {
...@@ -358,6 +366,10 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n) ...@@ -358,6 +366,10 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n)
#endif #endif
if (n->ht_down) if (n->ht_down)
n->ht_down->refcnt--; n->ht_down->refcnt--;
#ifdef CONFIG_CLS_U32_PERF
if (n && (NULL != n->pf))
kfree(n->pf);
#endif
kfree(n); kfree(n);
return 0; return 0;
} }
...@@ -571,18 +583,6 @@ static int u32_set_parms(struct Qdisc *q, unsigned long base, ...@@ -571,18 +583,6 @@ static int u32_set_parms(struct Qdisc *q, unsigned long base,
tcf_action_destroy(act, TCA_ACT_UNBIND); tcf_action_destroy(act, TCA_ACT_UNBIND);
} }
#ifdef CONFIG_NET_CLS_IND
n->indev[0] = 0;
if(tb[TCA_U32_INDEV-1]) {
struct rtattr *input_dev = tb[TCA_U32_INDEV-1];
if (RTA_PAYLOAD(input_dev) >= IFNAMSIZ) {
printk("cls_u32: bad indev name %s\n",(char*)RTA_DATA(input_dev));
/* should we clear state first? */
return -EINVAL;
}
sprintf(n->indev, "%s", (char*)RTA_DATA(input_dev));
}
#endif
#else #else
#ifdef CONFIG_NET_CLS_POLICE #ifdef CONFIG_NET_CLS_POLICE
...@@ -594,6 +594,19 @@ static int u32_set_parms(struct Qdisc *q, unsigned long base, ...@@ -594,6 +594,19 @@ static int u32_set_parms(struct Qdisc *q, unsigned long base,
tcf_police_release(police, TCA_ACT_UNBIND); tcf_police_release(police, TCA_ACT_UNBIND);
} }
#endif #endif
#endif
#ifdef CONFIG_NET_CLS_IND
n->indev[0] = 0;
if(tb[TCA_U32_INDEV-1]) {
struct rtattr *input_dev = tb[TCA_U32_INDEV-1];
if (RTA_PAYLOAD(input_dev) >= IFNAMSIZ) {
printk("cls_u32: bad indev name %s\n",(char*)RTA_DATA(input_dev));
/* should we clear state first? */
return -EINVAL;
}
sprintf(n->indev, "%s", (char*)RTA_DATA(input_dev));
printk("got IND %s\n",n->indev);
}
#endif #endif
return 0; return 0;
...@@ -682,17 +695,20 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, ...@@ -682,17 +695,20 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
s = RTA_DATA(tb[TCA_U32_SEL-1]); s = RTA_DATA(tb[TCA_U32_SEL-1]);
#ifdef CONFIG_CLS_U32_PERF
if (RTA_PAYLOAD(tb[TCA_U32_SEL-1]) <
(s->nkeys*sizeof(struct tc_u32_key)) + sizeof(struct tc_u32_sel)) {
printk("Please upgrade your iproute2 tools or compile proper options in!\n");
return -EINVAL;
}
#endif
n = kmalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL); n = kmalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
if (n == NULL) if (n == NULL)
return -ENOBUFS; return -ENOBUFS;
memset(n, 0, sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key)); memset(n, 0, sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key));
#ifdef CONFIG_CLS_U32_PERF
n->pf = kmalloc(sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(__u64), GFP_KERNEL);
if (n->pf == NULL) {
kfree(n);
return -ENOBUFS;
}
memset(n->pf, 0, sizeof(struct tc_u32_pcnt) + s->nkeys*sizeof(__u64));
#endif
memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key)); memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
n->ht_up = ht; n->ht_up = ht;
n->handle = handle; n->handle = handle;
...@@ -721,6 +737,10 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, ...@@ -721,6 +737,10 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
*arg = (unsigned long)n; *arg = (unsigned long)n;
return 0; return 0;
} }
#ifdef CONFIG_CLS_U32_PERF
if (n && (NULL != n->pf))
kfree(n->pf);
#endif
kfree(n); kfree(n);
return err; return err;
} }
...@@ -812,13 +832,6 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, ...@@ -812,13 +832,6 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
p_rta->rta_len = skb->tail - (u8*)p_rta; p_rta->rta_len = skb->tail - (u8*)p_rta;
} }
#ifdef CONFIG_NET_CLS_IND
if(strlen(n->indev)) {
struct rtattr * p_rta = (struct rtattr*)skb->tail;
RTA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev);
p_rta->rta_len = skb->tail - (u8*)p_rta;
}
#endif
#else #else
#ifdef CONFIG_NET_CLS_POLICE #ifdef CONFIG_NET_CLS_POLICE
...@@ -833,14 +846,29 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh, ...@@ -833,14 +846,29 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
} }
#endif #endif
#endif
#ifdef CONFIG_NET_CLS_IND
if(strlen(n->indev)) {
struct rtattr * p_rta = (struct rtattr*)skb->tail;
RTA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev);
p_rta->rta_len = skb->tail - (u8*)p_rta;
}
#endif
#ifdef CONFIG_CLS_U32_PERF
RTA_PUT(skb, TCA_U32_PCNT,
sizeof(struct tc_u32_pcnt) + n->sel.nkeys*sizeof(__u64),
n->pf);
#endif #endif
} }
rta->rta_len = skb->tail - b; rta->rta_len = skb->tail - b;
#ifdef CONFIG_NET_CLS_ACT #ifdef CONFIG_NET_CLS_ACT
if (TC_U32_KEY(n->handle) && n->action && n->action->type == TCA_OLD_COMPAT) { if (TC_U32_KEY(n->handle) != 0) {
if (tcf_action_copy_stats(skb,n->action)) if (TC_U32_KEY(n->handle) && n->action && n->action->type == TCA_OLD_COMPAT) {
goto rtattr_failure; if (tcf_action_copy_stats(skb,n->action))
goto rtattr_failure;
}
} }
#else #else
#ifdef CONFIG_NET_CLS_POLICE #ifdef CONFIG_NET_CLS_POLICE
...@@ -875,6 +903,19 @@ static struct tcf_proto_ops cls_u32_ops = { ...@@ -875,6 +903,19 @@ static struct tcf_proto_ops cls_u32_ops = {
static int __init init_u32(void) static int __init init_u32(void)
{ {
printk("u32 classifier\n");
#ifdef CONFIG_CLS_U32_PERF
printk(" Perfomance counters on\n");
#endif
#ifdef CONFIG_NET_CLS_POLICE
printk(" OLD policer on \n");
#endif
#ifdef CONFIG_NET_CLS_IND
printk(" input device check on \n");
#endif
#ifdef CONFIG_NET_CLS_ACT
printk(" Actions configured \n");
#endif
return register_tcf_proto_ops(&cls_u32_ops); return register_tcf_proto_ops(&cls_u32_ops);
} }
......
...@@ -8,6 +8,10 @@ menu "SCTP Configuration (EXPERIMENTAL)" ...@@ -8,6 +8,10 @@ menu "SCTP Configuration (EXPERIMENTAL)"
config IP_SCTP config IP_SCTP
tristate "The SCTP Protocol (EXPERIMENTAL)" tristate "The SCTP Protocol (EXPERIMENTAL)"
depends on IPV6 || IPV6=n depends on IPV6 || IPV6=n
select CRYPTO if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5
select CRYPTO_HMAC if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5
select CRYPTO_SHA1 if SCTP_HMAC_SHA1
select CRYPTO_MD5 if SCTP_HMAC_MD5
---help--- ---help---
Stream Control Transmission Protocol Stream Control Transmission Protocol
...@@ -71,18 +75,12 @@ config SCTP_HMAC_NONE ...@@ -71,18 +75,12 @@ config SCTP_HMAC_NONE
config SCTP_HMAC_SHA1 config SCTP_HMAC_SHA1
bool "HMAC-SHA1" bool "HMAC-SHA1"
select CRYPTO
select CRYPTO_HMAC
select CRYPTO_SHA1
help help
Enable the use of HMAC-SHA1 during association establishment. It Enable the use of HMAC-SHA1 during association establishment. It
is advised to use either HMAC-MD5 or HMAC-SHA1. is advised to use either HMAC-MD5 or HMAC-SHA1.
config SCTP_HMAC_MD5 config SCTP_HMAC_MD5
bool "HMAC-MD5" bool "HMAC-MD5"
select CRYPTO
select CRYPTO_HMAC
select CRYPTO_MD5
help help
Enable the use of HMAC-MD5 during association establishment. It is Enable the use of HMAC-MD5 during association establishment. It is
advised to use either HMAC-MD5 or HMAC-SHA1. advised to use either HMAC-MD5 or HMAC-SHA1.
......
...@@ -1296,21 +1296,6 @@ xprt_transmit(struct rpc_task *task) ...@@ -1296,21 +1296,6 @@ xprt_transmit(struct rpc_task *task)
/* /*
* Reserve an RPC call slot. * Reserve an RPC call slot.
*/ */
void
xprt_reserve(struct rpc_task *task)
{
struct rpc_xprt *xprt = task->tk_xprt;
task->tk_status = -EIO;
if (!xprt->shutdown) {
spin_lock(&xprt->xprt_lock);
do_xprt_reserve(task);
spin_unlock(&xprt->xprt_lock);
if (task->tk_rqstp)
del_timer_sync(&xprt->timer);
}
}
static inline void static inline void
do_xprt_reserve(struct rpc_task *task) do_xprt_reserve(struct rpc_task *task)
{ {
...@@ -1332,6 +1317,21 @@ do_xprt_reserve(struct rpc_task *task) ...@@ -1332,6 +1317,21 @@ do_xprt_reserve(struct rpc_task *task)
rpc_sleep_on(&xprt->backlog, task, NULL, NULL); rpc_sleep_on(&xprt->backlog, task, NULL, NULL);
} }
void
xprt_reserve(struct rpc_task *task)
{
struct rpc_xprt *xprt = task->tk_xprt;
task->tk_status = -EIO;
if (!xprt->shutdown) {
spin_lock(&xprt->xprt_lock);
do_xprt_reserve(task);
spin_unlock(&xprt->xprt_lock);
if (task->tk_rqstp)
del_timer_sync(&xprt->timer);
}
}
/* /*
* Allocate a 'unique' XID * Allocate a 'unique' XID
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment