Skip to content

Commit

Permalink
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Browse files Browse the repository at this point in the history
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [BRIDGE]: Unaligned access when comparing ethernet addresses
  [SCTP]: Unmap v4mapped addresses during SCTP_BINDX_REM_ADDR operation.
  [SCTP]: Fix assertion (!atomic_read(&sk->sk_rmem_alloc)) failed message
  [NET]: Set a separate lockdep class for neighbour table's proxy_queue
  [NET]: Fix UDP checksum issue in net poll mode.
  [KEY]: Fix conversion between IPSEC_MODE_xxx and XFRM_MODE_xxx.
  [NET]: Get rid of alloc_skb_from_cache
  • Loading branch information
Linus Torvalds committed Apr 17, 2007
2 parents 245d95a + 19bb350 commit 80d74d5
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 81 deletions.
1 change: 0 additions & 1 deletion arch/x86_64/kernel/functionlist
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,6 @@
*(.text.dentry_open)
*(.text.dentry_iput)
*(.text.bio_alloc)
*(.text.alloc_skb_from_cache)
*(.text.wait_on_page_bit)
*(.text.vfs_readdir)
*(.text.vfs_lstat)
Expand Down
10 changes: 7 additions & 3 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,6 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
return __alloc_skb(size, priority, 1, -1);
}

extern struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp,
unsigned int size,
gfp_t priority);
extern void kfree_skbmem(struct sk_buff *skb);
extern struct sk_buff *skb_clone(struct sk_buff *skb,
gfp_t priority);
Expand Down Expand Up @@ -622,6 +619,13 @@ static inline void skb_queue_head_init(struct sk_buff_head *list)
list->qlen = 0;
}

static inline void skb_queue_head_init_class(struct sk_buff_head *list,
struct lock_class_key *class)
{
skb_queue_head_init(list);
lockdep_set_class(&list->lock, class);
}

/*
* Insert an sk_buff at the start of a list.
*
Expand Down
9 changes: 7 additions & 2 deletions net/bridge/br_stp_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ void br_stp_disable_port(struct net_bridge_port *p)
/* called under bridge lock */
void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
{
unsigned char oldaddr[6];
/* should be aligned on 2 bytes for compare_ether_addr() */
unsigned short oldaddr_aligned[ETH_ALEN >> 1];
unsigned char *oldaddr = (unsigned char *)oldaddr_aligned;
struct net_bridge_port *p;
int wasroot;

Expand All @@ -151,11 +153,14 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
br_become_root_bridge(br);
}

static const unsigned char br_mac_zero[6];
/* should be aligned on 2 bytes for compare_ether_addr() */
static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1];

/* called under bridge lock */
void br_stp_recalculate_bridge_id(struct net_bridge *br)
{
const unsigned char *br_mac_zero =
(const unsigned char *)br_mac_zero_aligned;
const unsigned char *addr = br_mac_zero;
struct net_bridge_port *p;

Expand Down
5 changes: 4 additions & 1 deletion net/core/neighbour.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,8 @@ void neigh_parms_destroy(struct neigh_parms *parms)
kfree(parms);
}

static struct lock_class_key neigh_table_proxy_queue_class;

void neigh_table_init_no_netlink(struct neigh_table *tbl)
{
unsigned long now = jiffies;
Expand Down Expand Up @@ -1379,7 +1381,8 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
init_timer(&tbl->proxy_timer);
tbl->proxy_timer.data = (unsigned long)tbl;
tbl->proxy_timer.function = neigh_proxy_process;
skb_queue_head_init(&tbl->proxy_queue);
skb_queue_head_init_class(&tbl->proxy_queue,
&neigh_table_proxy_queue_class);

tbl->last_flush = now;
tbl->last_rand = now + tbl->parms.reachable_time * 20;
Expand Down
7 changes: 7 additions & 0 deletions net/core/netpoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,13 @@ int __netpoll_rx(struct sk_buff *skb)
if (skb->len < len || len < iph->ihl*4)
goto out;

/*
* Our transport medium may have padded the buffer out.
* Now We trim to the true length of the frame.
*/
if (pskb_trim_rcsum(skb, len))
goto out;

if (iph->protocol != IPPROTO_UDP)
goto out;

Expand Down
55 changes: 0 additions & 55 deletions net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,61 +196,6 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
goto out;
}

/**
* alloc_skb_from_cache - allocate a network buffer
* @cp: kmem_cache from which to allocate the data area
* (object size must be big enough for @size bytes + skb overheads)
* @size: size to allocate
* @gfp_mask: allocation mask
*
* Allocate a new &sk_buff. The returned buffer has no headroom and
* tail room of size bytes. The object has a reference count of one.
* The return is the buffer. On a failure the return is %NULL.
*
* Buffers may only be allocated from interrupts using a @gfp_mask of
* %GFP_ATOMIC.
*/
struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp,
unsigned int size,
gfp_t gfp_mask)
{
struct sk_buff *skb;
u8 *data;

/* Get the HEAD */
skb = kmem_cache_alloc(skbuff_head_cache,
gfp_mask & ~__GFP_DMA);
if (!skb)
goto out;

/* Get the DATA. */
size = SKB_DATA_ALIGN(size);
data = kmem_cache_alloc(cp, gfp_mask);
if (!data)
goto nodata;

memset(skb, 0, offsetof(struct sk_buff, truesize));
skb->truesize = size + sizeof(struct sk_buff);
atomic_set(&skb->users, 1);
skb->head = data;
skb->data = data;
skb->tail = data;
skb->end = data + size;

atomic_set(&(skb_shinfo(skb)->dataref), 1);
skb_shinfo(skb)->nr_frags = 0;
skb_shinfo(skb)->gso_size = 0;
skb_shinfo(skb)->gso_segs = 0;
skb_shinfo(skb)->gso_type = 0;
skb_shinfo(skb)->frag_list = NULL;
out:
return skb;
nodata:
kmem_cache_free(skbuff_head_cache, skb);
skb = NULL;
goto out;
}

/**
* __netdev_alloc_skb - allocate an skbuff for rx on a specific device
* @dev: network device to receive on
Expand Down
90 changes: 75 additions & 15 deletions net/key/af_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,35 @@ pfkey_sockaddr_size(sa_family_t family)
/* NOTREACHED */
}

static inline int pfkey_mode_from_xfrm(int mode)
{
switch(mode) {
case XFRM_MODE_TRANSPORT:
return IPSEC_MODE_TRANSPORT;
case XFRM_MODE_TUNNEL:
return IPSEC_MODE_TUNNEL;
case XFRM_MODE_BEET:
return IPSEC_MODE_BEET;
default:
return -1;
}
}

static inline int pfkey_mode_to_xfrm(int mode)
{
switch(mode) {
case IPSEC_MODE_ANY: /*XXX*/
case IPSEC_MODE_TRANSPORT:
return XFRM_MODE_TRANSPORT;
case IPSEC_MODE_TUNNEL:
return XFRM_MODE_TUNNEL;
case IPSEC_MODE_BEET:
return XFRM_MODE_BEET;
default:
return -1;
}
}

static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, int hsc)
{
struct sk_buff *skb;
Expand All @@ -651,6 +680,7 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
int encrypt_key_size = 0;
int sockaddr_size;
struct xfrm_encap_tmpl *natt = NULL;
int mode;

/* address family check */
sockaddr_size = pfkey_sockaddr_size(x->props.family);
Expand Down Expand Up @@ -928,7 +958,11 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
sa2 = (struct sadb_x_sa2 *) skb_put(skb, sizeof(struct sadb_x_sa2));
sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2)/sizeof(uint64_t);
sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
sa2->sadb_x_sa2_mode = x->props.mode + 1;
if ((mode = pfkey_mode_from_xfrm(x->props.mode)) < 0) {
kfree_skb(skb);
return ERR_PTR(-EINVAL);
}
sa2->sadb_x_sa2_mode = mode;
sa2->sadb_x_sa2_reserved1 = 0;
sa2->sadb_x_sa2_reserved2 = 0;
sa2->sadb_x_sa2_sequence = 0;
Expand Down Expand Up @@ -1155,9 +1189,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,

if (ext_hdrs[SADB_X_EXT_SA2-1]) {
struct sadb_x_sa2 *sa2 = (void*)ext_hdrs[SADB_X_EXT_SA2-1];
x->props.mode = sa2->sadb_x_sa2_mode;
if (x->props.mode)
x->props.mode--;
int mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode);
if (mode < 0) {
err = -EINVAL;
goto out;
}
x->props.mode = mode;
x->props.reqid = sa2->sadb_x_sa2_reqid;
}

Expand Down Expand Up @@ -1218,7 +1255,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
struct sadb_address *saddr, *daddr;
struct sadb_msg *out_hdr;
struct xfrm_state *x = NULL;
u8 mode;
int mode;
u32 reqid;
u8 proto;
unsigned short family;
Expand All @@ -1233,7 +1270,9 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
return -EINVAL;

if ((sa2 = ext_hdrs[SADB_X_EXT_SA2-1]) != NULL) {
mode = sa2->sadb_x_sa2_mode - 1;
mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode);
if (mode < 0)
return -EINVAL;
reqid = sa2->sadb_x_sa2_reqid;
} else {
mode = 0;
Expand Down Expand Up @@ -1756,6 +1795,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct sockaddr_in6 *sin6;
#endif
int mode;

if (xp->xfrm_nr >= XFRM_MAX_DEPTH)
return -ELOOP;
Expand All @@ -1764,7 +1804,9 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
return -EINVAL;

t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */
t->mode = rq->sadb_x_ipsecrequest_mode-1;
if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
return -EINVAL;
t->mode = mode;
if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)
t->optional = 1;
else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
Expand Down Expand Up @@ -1877,7 +1919,7 @@ static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp)
return skb;
}

static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, int dir)
static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, int dir)
{
struct sadb_msg *hdr;
struct sadb_address *addr;
Expand Down Expand Up @@ -2014,6 +2056,7 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
struct sadb_x_ipsecrequest *rq;
struct xfrm_tmpl *t = xp->xfrm_vec + i;
int req_size;
int mode;

req_size = sizeof(struct sadb_x_ipsecrequest);
if (t->mode == XFRM_MODE_TUNNEL)
Expand All @@ -2027,7 +2070,9 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
memset(rq, 0, sizeof(*rq));
rq->sadb_x_ipsecrequest_len = req_size;
rq->sadb_x_ipsecrequest_proto = t->id.proto;
rq->sadb_x_ipsecrequest_mode = t->mode+1;
if ((mode = pfkey_mode_from_xfrm(t->mode)) < 0)
return -EINVAL;
mode = pfkey_mode_from_xfrm(t->mode);
rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
if (t->reqid)
rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
Expand Down Expand Up @@ -2089,6 +2134,8 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i

hdr->sadb_msg_len = size / sizeof(uint64_t);
hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);

return 0;
}

static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
Expand All @@ -2102,7 +2149,9 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c
err = PTR_ERR(out_skb);
goto out;
}
pfkey_xfrm_policy2msg(out_skb, xp, dir);
err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
if (err < 0)
return err;

out_hdr = (struct sadb_msg *) out_skb->data;
out_hdr->sadb_msg_version = PF_KEY_V2;
Expand Down Expand Up @@ -2327,7 +2376,9 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb
err = PTR_ERR(out_skb);
goto out;
}
pfkey_xfrm_policy2msg(out_skb, xp, dir);
err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
if (err < 0)
goto out;

out_hdr = (struct sadb_msg *) out_skb->data;
out_hdr->sadb_msg_version = hdr->sadb_msg_version;
Expand Down Expand Up @@ -2409,6 +2460,7 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
{
int err;
struct sadb_x_ipsecrequest *rq2;
int mode;

if (len <= sizeof(struct sadb_x_ipsecrequest) ||
len < rq1->sadb_x_ipsecrequest_len)
Expand Down Expand Up @@ -2439,7 +2491,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
return -EINVAL;

m->proto = rq1->sadb_x_ipsecrequest_proto;
m->mode = rq1->sadb_x_ipsecrequest_mode - 1;
if ((mode = pfkey_mode_to_xfrm(rq1->sadb_x_ipsecrequest_mode)) < 0)
return -EINVAL;
m->mode = mode;
m->reqid = rq1->sadb_x_ipsecrequest_reqid;

return ((int)(rq1->sadb_x_ipsecrequest_len +
Expand Down Expand Up @@ -2579,12 +2633,15 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
struct pfkey_dump_data *data = ptr;
struct sk_buff *out_skb;
struct sadb_msg *out_hdr;
int err;

out_skb = pfkey_xfrm_policy2msg_prep(xp);
if (IS_ERR(out_skb))
return PTR_ERR(out_skb);

pfkey_xfrm_policy2msg(out_skb, xp, dir);
err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
if (err < 0)
return err;

out_hdr = (struct sadb_msg *) out_skb->data;
out_hdr->sadb_msg_version = data->hdr->sadb_msg_version;
Expand Down Expand Up @@ -3513,15 +3570,18 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,

for (i = 0, mp = m; i < num_bundles; i++, mp++) {
/* old ipsecrequest */
if (set_ipsecrequest(skb, mp->proto, mp->mode + 1,
int mode = pfkey_mode_from_xfrm(mp->mode);
if (mode < 0)
return -EINVAL;
if (set_ipsecrequest(skb, mp->proto, mode,
(mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
mp->reqid, mp->old_family,
&mp->old_saddr, &mp->old_daddr) < 0) {
return -EINVAL;
}

/* new ipsecrequest */
if (set_ipsecrequest(skb, mp->proto, mp->mode + 1,
if (set_ipsecrequest(skb, mp->proto, mode,
(mp->reqid ? IPSEC_LEVEL_UNIQUE : IPSEC_LEVEL_REQUIRE),
mp->reqid, mp->new_family,
&mp->new_saddr, &mp->new_daddr) < 0) {
Expand Down
Loading

0 comments on commit 80d74d5

Please sign in to comment.