Module Name: src Committed By: rmind Date: Fri Nov 5 01:35:58 UTC 2010
Modified Files: src/sys/dist/pf/net: if_pfsync.c pf_norm.c src/sys/netinet: in_var.h ip_id.c ip_input.c Log Message: ip_randomid: make mechanism MP-safe and more modular. OK matt@ To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/dist/pf/net/if_pfsync.c cvs rdiff -u -r1.22 -r1.23 src/sys/dist/pf/net/pf_norm.c cvs rdiff -u -r1.64 -r1.65 src/sys/netinet/in_var.h cvs rdiff -u -r1.13 -r1.14 src/sys/netinet/ip_id.c cvs rdiff -u -r1.290 -r1.291 src/sys/netinet/ip_input.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dist/pf/net/if_pfsync.c diff -u src/sys/dist/pf/net/if_pfsync.c:1.6 src/sys/dist/pf/net/if_pfsync.c:1.7 --- src/sys/dist/pf/net/if_pfsync.c:1.6 Mon Apr 5 07:22:22 2010 +++ src/sys/dist/pf/net/if_pfsync.c Fri Nov 5 01:35:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: if_pfsync.c,v 1.6 2010/04/05 07:22:22 joerg Exp $ */ +/* $NetBSD: if_pfsync.c,v 1.7 2010/11/05 01:35:58 rmind Exp $ */ /* $OpenBSD: if_pfsync.c,v 1.83 2007/06/26 14:44:12 mcbride Exp $ */ /* @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_pfsync.c,v 1.6 2010/04/05 07:22:22 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_pfsync.c,v 1.7 2010/11/05 01:35:58 rmind Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1599,7 +1599,7 @@ ip->ip_hl = sizeof(*ip) >> 2; ip->ip_tos = IPTOS_LOWDELAY; ip->ip_len = htons(m->m_pkthdr.len); - ip->ip_id = htons(ip_randomid(0)); + ip->ip_id = htons(ip_randomid(ip_ids, 0)); ip->ip_off = htons(IP_DF); ip->ip_ttl = PFSYNC_DFLTTL; ip->ip_p = IPPROTO_PFSYNC; Index: src/sys/dist/pf/net/pf_norm.c diff -u src/sys/dist/pf/net/pf_norm.c:1.22 src/sys/dist/pf/net/pf_norm.c:1.23 --- src/sys/dist/pf/net/pf_norm.c:1.22 Mon Apr 12 13:57:38 2010 +++ src/sys/dist/pf/net/pf_norm.c Fri Nov 5 01:35:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: pf_norm.c,v 1.22 2010/04/12 13:57:38 ahoka Exp $ */ +/* $NetBSD: pf_norm.c,v 1.23 2010/11/05 01:35:58 rmind Exp $ */ /* $OpenBSD: pf_norm.c,v 1.109 2007/05/28 17:16:39 henning Exp $ */ /* @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pf_norm.c,v 1.22 2010/04/12 13:57:38 ahoka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pf_norm.c,v 1.23 2010/11/05 01:35:58 rmind Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1046,7 +1046,7 @@ if (r->rule_flag & PFRULE_RANDOMID) { u_int16_t ip_id = h->ip_id; - h->ip_id = ip_randomid(0); + h->ip_id = ip_randomid(ip_ids, 0); h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_id, h->ip_id, 0); } if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0) Index: src/sys/netinet/in_var.h diff -u src/sys/netinet/in_var.h:1.64 src/sys/netinet/in_var.h:1.65 --- src/sys/netinet/in_var.h:1.64 Mon Jul 19 14:09:44 2010 +++ src/sys/netinet/in_var.h Fri Nov 5 01:35:57 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: in_var.h,v 1.64 2010/07/19 14:09:44 rmind Exp $ */ +/* $NetBSD: in_var.h,v 1.65 2010/11/05 01:35:57 rmind Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -302,44 +302,47 @@ void in_purgeif(struct ifnet *); void ip_input(struct mbuf *); int ipflow_fastforward(struct mbuf *); -void ip_initid(void); -extern uint16_t ip_id; -static __inline uint16_t ip_newid(const struct in_ifaddr *); -uint16_t ip_randomid(uint16_t); -extern int ip_do_randomid; +struct ipid_state; +typedef struct ipid_state ipid_state_t; + +ipid_state_t * ip_id_init(void); +void ip_id_fini(ipid_state_t *); +uint16_t ip_randomid(ipid_state_t *, uint16_t); + +extern ipid_state_t * ip_ids; +extern uint16_t ip_id; +extern int ip_do_randomid; /* - * ip_newid_range: "allocate" num contiguous ip_ids. + * ip_newid_range: "allocate" num contiguous IP IDs. * - * => return the first id. + * => Return the first ID. */ - static __inline uint16_t -ip_newid_range(const struct in_ifaddr *ia, unsigned int num) +ip_newid_range(const struct in_ifaddr *ia, u_int num) { uint16_t id; if (ip_do_randomid) { /* XXX ignore num */ - return ip_randomid(ia ? ia->ia_idsalt : 0); + return ip_randomid(ip_ids, ia ? ia->ia_idsalt : 0); } - /* - * never allow an ip_id of 0. (detect wrap) - */ - if ((uint16_t)(ip_id + num) < ip_id) + /* Never allow an IP ID of 0 (detect wrap). */ + if ((uint16_t)(ip_id + num) < ip_id) { ip_id = 1; + } id = htons(ip_id); ip_id += num; - return id; } static __inline uint16_t ip_newid(const struct in_ifaddr *ia) { + return ip_newid_range(ia, 1); } @@ -347,7 +350,7 @@ int sysctl_inpcblist(SYSCTLFN_PROTO); #endif -#endif +#endif /* !_KERNEL */ /* INET6 stuff */ #include <netinet6/in6_var.h> Index: src/sys/netinet/ip_id.c diff -u src/sys/netinet/ip_id.c:1.13 src/sys/netinet/ip_id.c:1.14 --- src/sys/netinet/ip_id.c:1.13 Thu Nov 4 22:00:51 2010 +++ src/sys/netinet/ip_id.c Fri Nov 5 01:35:57 2010 @@ -1,5 +1,4 @@ -/* $NetBSD: ip_id.c,v 1.13 2010/11/04 22:00:51 matt Exp $ */ -/* $OpenBSD: ip_id.c,v 1.6 2002/03/15 18:19:52 millert Exp $ */ +/* $NetBSD: ip_id.c,v 1.14 2010/11/05 01:35:57 rmind Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -31,24 +30,26 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_id.c,v 1.13 2010/11/04 22:00:51 matt Exp $"); - -#include "opt_inet.h" +__KERNEL_RCSID(0, "$NetBSD: ip_id.c,v 1.14 2010/11/05 01:35:57 rmind Exp $"); #include <sys/param.h> -#include <lib/libkern/libkern.h> +#include <sys/kmem.h> +#include <sys/mutex.h> #include <net/if.h> #include <netinet/in.h> #include <netinet/in_var.h> +#include <lib/libkern/libkern.h> + #define IPID_MAXID 65535 #define IPID_NUMIDS 32768 -static struct ipid_state { - uint16_t ids_start_slot; - uint16_t ids_slots[IPID_MAXID]; -} idstate; +struct ipid_state { + kmutex_t ids_lock; + uint16_t ids_start_slot; + uint16_t ids_slots[IPID_MAXID]; +}; static inline uint32_t ipid_random(void) @@ -64,34 +65,46 @@ * This function is called from id_randomid() when needed, an * application does not have to worry about it. */ -void -ip_initid(void) +ipid_state_t * +ip_id_init(void) { + ipid_state_t *ids; size_t i; - idstate.ids_start_slot = ipid_random(); - for (i = 0; i < __arraycount(idstate.ids_slots); i++) - idstate.ids_slots[i] = i; + ids = kmem_alloc(sizeof(ipid_state_t), KM_SLEEP); + mutex_init(&ids->ids_lock, MUTEX_DEFAULT, IPL_SOFTNET); + + ids->ids_start_slot = ipid_random(); + for (i = 0; i < __arraycount(ids->ids_slots); i++) { + ids->ids_slots[i] = i; + } /* * Shuffle the array. */ - for (i = __arraycount(idstate.ids_slots); --i > 0;) { + for (i = __arraycount(ids->ids_slots); --i > 0;) { size_t k = ipid_random() % (i + 1); - uint16_t t = idstate.ids_slots[i]; - idstate.ids_slots[i] = idstate.ids_slots[k]; - idstate.ids_slots[k] = t; + uint16_t t = ids->ids_slots[i]; + ids->ids_slots[i] = ids->ids_slots[k]; + ids->ids_slots[k] = t; } + return ids; +} + +void +ip_id_fini(ipid_state_t *ids) +{ + + mutex_destroy(&ids->ids_lock); + kmem_free(ids, sizeof(ipid_state_t)); } uint16_t -ip_randomid(uint16_t salt) +ip_randomid(ipid_state_t *ids, uint16_t salt) { uint32_t r, k, id; - /* - * We need a random number - */ + /* A random number. */ r = ipid_random(); /* @@ -100,7 +113,7 @@ * then advance the start of the window by 1. The next time that * swapped-out entry can be used is at least 32768 iterations in the * future. - * + * * The easiest way to visual this is to imagine a card deck with 52 * cards. First thing we do is split that into two sets, each with * half of the cards; call them deck A and deck B. Pick a card @@ -108,23 +121,27 @@ * bottom of deck B. Then take the top card from deck B and add it * to deck A. Pick another card randomly from deck A and ... */ - k = (r & (IPID_NUMIDS-1)) + idstate.ids_start_slot; - if (k >= IPID_MAXID) + mutex_enter(&ids->ids_lock); + k = (r & (IPID_NUMIDS - 1)) + ids->ids_start_slot; + if (k >= IPID_MAXID) { k -= IPID_MAXID; - - id = idstate.ids_slots[k]; - if (k != idstate.ids_start_slot) { - idstate.ids_slots[k] = idstate.ids_slots[idstate.ids_start_slot]; - idstate.ids_slots[idstate.ids_start_slot] = id; } - if (++idstate.ids_start_slot == IPID_MAXID) - idstate.ids_start_slot = 0; + id = ids->ids_slots[k]; + if (k != ids->ids_start_slot) { + ids->ids_slots[k] = ids->ids_slots[ids->ids_start_slot]; + ids->ids_slots[ids->ids_start_slot] = id; + } + if (++ids->ids_start_slot == IPID_MAXID) { + ids->ids_start_slot = 0; + } + mutex_exit(&ids->ids_lock); + /* * Add an optional salt to the id to further obscure it. */ id += salt; - if (id >= IPID_MAXID) + if (id >= IPID_MAXID) { id -= IPID_MAXID; - - return (uint16_t) htons(id + 1); + } + return (uint16_t)htons(id + 1); } Index: src/sys/netinet/ip_input.c diff -u src/sys/netinet/ip_input.c:1.290 src/sys/netinet/ip_input.c:1.291 --- src/sys/netinet/ip_input.c:1.290 Fri Nov 5 00:21:51 2010 +++ src/sys/netinet/ip_input.c Fri Nov 5 01:35:57 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.290 2010/11/05 00:21:51 rmind Exp $ */ +/* $NetBSD: ip_input.c,v 1.291 2010/11/05 01:35:57 rmind Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,7 +91,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.290 2010/11/05 00:21:51 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.291 2010/11/05 01:35:57 rmind Exp $"); #include "opt_inet.h" #include "opt_compat_netbsd.h" @@ -231,6 +231,7 @@ struct in_multihashhead *in_multihashtbl; struct ifqueue ipintrq; +ipid_state_t * ip_ids; uint16_t ip_id; percpu_t *ipstat_percpu; @@ -315,7 +316,7 @@ ip_reass_init(); - ip_initid(); + ip_ids = ip_id_init(); ip_id = time_second & 0xfffff; ipintrq.ifq_maxlen = ipqmaxlen;