Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/klassert/ipsec-next

Steffen Klassert says:

====================
pull request (net-next): ipsec-next 2014-09-25

1) Remove useless hash_resize_mutex in xfrm_hash_resize().
   This mutex is used only there, but xfrm_hash_resize()
   can't be called concurrently at all. From Ying Xue.

2) Extend policy hashing to prefixed policies based on
   prefix lenght thresholds. From Christophe Gouault.

3) Make the policy hash table thresholds configurable
   via netlink. From Christophe Gouault.

4) Remove the maximum authentication length for AH.
   This was needed to limit stack usage. We switched
   already to allocate space, so no need to keep the
   limit. From Herbert Xu.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 28, 2014
2 parents fe2c5fb + 689f1c9 commit f5c7e1a
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 38 deletions.
3 changes: 0 additions & 3 deletions include/net/ah.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@

#include <linux/skbuff.h>

/* This is the maximum truncated ICV length that we know of. */
#define MAX_AH_AUTH_LEN 64

struct crypto_ahash;

struct ah_data {
Expand Down
14 changes: 14 additions & 0 deletions include/net/netns/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ struct ctl_table_header;
struct xfrm_policy_hash {
struct hlist_head *table;
unsigned int hmask;
u8 dbits4;
u8 sbits4;
u8 dbits6;
u8 sbits6;
};

struct xfrm_policy_hthresh {
struct work_struct work;
seqlock_t lock;
u8 lbits4;
u8 rbits4;
u8 lbits6;
u8 rbits6;
};

struct netns_xfrm {
Expand Down Expand Up @@ -41,6 +54,7 @@ struct netns_xfrm {
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2];
unsigned int policy_count[XFRM_POLICY_MAX * 2];
struct work_struct policy_hash_work;
struct xfrm_policy_hthresh policy_hthresh;


struct sock *nlsk;
Expand Down
1 change: 1 addition & 0 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1591,6 +1591,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir,
u32 id, int delete, int *err);
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid);
void xfrm_policy_hash_rebuild(struct net *net);
u32 xfrm_get_acqseq(void);
int verify_spi_info(u8 proto, u32 min, u32 max);
int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
Expand Down
7 changes: 7 additions & 0 deletions include/uapi/linux/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ enum xfrm_spdattr_type_t {
XFRMA_SPD_UNSPEC,
XFRMA_SPD_INFO,
XFRMA_SPD_HINFO,
XFRMA_SPD_IPV4_HTHRESH,
XFRMA_SPD_IPV6_HTHRESH,
__XFRMA_SPD_MAX

#define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1)
Expand All @@ -347,6 +349,11 @@ struct xfrmu_spdhinfo {
__u32 spdhmcnt;
};

struct xfrmu_spdhthresh {
__u8 lbits;
__u8 rbits;
};

struct xfrm_usersa_info {
struct xfrm_selector sel;
struct xfrm_id id;
Expand Down
2 changes: 0 additions & 2 deletions net/ipv4/ah4.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,8 +505,6 @@ static int ah_init_state(struct xfrm_state *x)
ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
ahp->icv_trunc_len = x->aalg->alg_trunc_len/8;

BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN);

if (x->props.flags & XFRM_STATE_ALIGN4)
x->props.header_len = XFRM_ALIGN4(sizeof(struct ip_auth_hdr) +
ahp->icv_trunc_len);
Expand Down
2 changes: 0 additions & 2 deletions net/ipv6/ah6.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,6 @@ static int ah6_init_state(struct xfrm_state *x)
ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;
ahp->icv_trunc_len = x->aalg->alg_trunc_len/8;

BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN);

x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
ahp->icv_trunc_len);
switch (x->props.mode) {
Expand Down
76 changes: 66 additions & 10 deletions net/xfrm/xfrm_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <linux/xfrm.h>
#include <linux/socket.h>
#include <linux/jhash.h>

static inline unsigned int __xfrm4_addr_hash(const xfrm_address_t *addr)
{
Expand All @@ -28,6 +29,58 @@ static inline unsigned int __xfrm6_daddr_saddr_hash(const xfrm_address_t *daddr,
saddr->a6[2] ^ saddr->a6[3]);
}

static inline u32 __bits2mask32(__u8 bits)
{
u32 mask32 = 0xffffffff;

if (bits == 0)
mask32 = 0;
else if (bits < 32)
mask32 <<= (32 - bits);

return mask32;
}

static inline unsigned int __xfrm4_dpref_spref_hash(const xfrm_address_t *daddr,
const xfrm_address_t *saddr,
__u8 dbits,
__u8 sbits)
{
return jhash_2words(ntohl(daddr->a4) & __bits2mask32(dbits),
ntohl(saddr->a4) & __bits2mask32(sbits),
0);
}

static inline unsigned int __xfrm6_pref_hash(const xfrm_address_t *addr,
__u8 prefixlen)
{
int pdw;
int pbi;
u32 initval = 0;

pdw = prefixlen >> 5; /* num of whole u32 in prefix */
pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */

if (pbi) {
__be32 mask;

mask = htonl((0xffffffff) << (32 - pbi));

initval = (__force u32)(addr->a6[pdw] & mask);
}

return jhash2((__force u32 *)addr->a6, pdw, initval);
}

static inline unsigned int __xfrm6_dpref_spref_hash(const xfrm_address_t *daddr,
const xfrm_address_t *saddr,
__u8 dbits,
__u8 sbits)
{
return __xfrm6_pref_hash(daddr, dbits) ^
__xfrm6_pref_hash(saddr, sbits);
}

static inline unsigned int __xfrm_dst_hash(const xfrm_address_t *daddr,
const xfrm_address_t *saddr,
u32 reqid, unsigned short family,
Expand Down Expand Up @@ -84,27 +137,28 @@ static inline unsigned int __idx_hash(u32 index, unsigned int hmask)
}

static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
unsigned short family, unsigned int hmask)
unsigned short family, unsigned int hmask,
u8 dbits, u8 sbits)
{
const xfrm_address_t *daddr = &sel->daddr;
const xfrm_address_t *saddr = &sel->saddr;
unsigned int h = 0;

switch (family) {
case AF_INET:
if (sel->prefixlen_d != 32 ||
sel->prefixlen_s != 32)
if (sel->prefixlen_d < dbits ||
sel->prefixlen_s < sbits)
return hmask + 1;

h = __xfrm4_daddr_saddr_hash(daddr, saddr);
h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;

case AF_INET6:
if (sel->prefixlen_d != 128 ||
sel->prefixlen_s != 128)
if (sel->prefixlen_d < dbits ||
sel->prefixlen_s < sbits)
return hmask + 1;

h = __xfrm6_daddr_saddr_hash(daddr, saddr);
h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
}
h ^= (h >> 16);
Expand All @@ -113,17 +167,19 @@ static inline unsigned int __sel_hash(const struct xfrm_selector *sel,

static inline unsigned int __addr_hash(const xfrm_address_t *daddr,
const xfrm_address_t *saddr,
unsigned short family, unsigned int hmask)
unsigned short family,
unsigned int hmask,
u8 dbits, u8 sbits)
{
unsigned int h = 0;

switch (family) {
case AF_INET:
h = __xfrm4_daddr_saddr_hash(daddr, saddr);
h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;

case AF_INET6:
h = __xfrm6_daddr_saddr_hash(daddr, saddr);
h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
}
h ^= (h >> 16);
Expand Down
Loading

0 comments on commit f5c7e1a

Please sign in to comment.