Adds a hash table to speed local address lookup
on a per VRF basis (BSD has only one VRF currently). Hash table is sized to 16 but may need to be adjusted for machines with large numbers of addresses. Reviewed by: gnn
This commit is contained in:
parent
46d98f5737
commit
6a27c37636
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=167698
@ -116,6 +116,8 @@ __FBSDID("$FreeBSD$");
|
||||
#define SCTP_SIZE_OF_VRF_HASH 3
|
||||
#define SCTP_IFNAMSIZ IFNAMSIZ
|
||||
#define SCTP_DEFAULT_VRFID 0
|
||||
#define SCTP_VRF_HASH_SIZE 16
|
||||
|
||||
|
||||
#define SCTP_IFN_IS_IFT_LOOP(ifn) ((ifn)->ifn_type == IFT_LOOP)
|
||||
|
||||
|
@ -155,6 +155,16 @@ sctp_allocate_vrf(int vrfid)
|
||||
vrf->vrf_id = vrfid;
|
||||
LIST_INIT(&vrf->ifnlist);
|
||||
vrf->total_ifa_count = 0;
|
||||
/* Init the HASH of addresses */
|
||||
vrf->vrf_addr_hash = SCTP_HASH_INIT(SCTP_VRF_HASH_SIZE,
|
||||
&vrf->vrf_hashmark);
|
||||
if (vrf->vrf_addr_hash == NULL) {
|
||||
/* No memory */
|
||||
#ifdef INVARIANTS
|
||||
panic("No memory for VRF:%d", vrfid);
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
/* Add it to the hash table */
|
||||
bucket = &sctppcbinfo.sctp_vrfhash[(vrfid & sctppcbinfo.hashvrfmark)];
|
||||
LIST_INSERT_HEAD(bucket, vrf, next_vrf);
|
||||
@ -217,6 +227,8 @@ sctp_add_addr_to_vrf(uint32_t vrfid, void *ifn, uint32_t ifn_index,
|
||||
struct sctp_vrf *vrf;
|
||||
struct sctp_ifn *sctp_ifnp = NULL;
|
||||
struct sctp_ifa *sctp_ifap = NULL;
|
||||
struct sctp_ifalist *hash_head;
|
||||
uint32_t hash_of_addr;
|
||||
|
||||
/* How granular do we need the locks to be here? */
|
||||
SCTP_IPI_ADDR_LOCK();
|
||||
@ -325,11 +337,15 @@ sctp_add_addr_to_vrf(uint32_t vrfid, void *ifn, uint32_t ifn_index,
|
||||
sctp_ifap->src_is_priv = 1;
|
||||
}
|
||||
}
|
||||
hash_of_addr = sctp_get_ifa_hash_val(&sctp_ifap->address.sa);
|
||||
|
||||
if ((sctp_ifap->src_is_priv == 0) &&
|
||||
(sctp_ifap->src_is_loop == 0)) {
|
||||
sctp_ifap->src_is_glob = 1;
|
||||
}
|
||||
SCTP_IPI_ADDR_LOCK();
|
||||
hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_hashmark)];
|
||||
LIST_INSERT_HEAD(hash_head, sctp_ifap, next_bucket);
|
||||
sctp_ifap->refcount = 1;
|
||||
LIST_INSERT_HEAD(&sctp_ifnp->ifalist, sctp_ifap, next_ifa);
|
||||
sctp_ifnp->ifa_count++;
|
||||
@ -365,6 +381,7 @@ sctp_del_addr_from_vrf(uint32_t vrfid, struct sockaddr *addr,
|
||||
sctp_ifap->localifa_flags |= SCTP_BEING_DELETED;
|
||||
sctp_ifnp->ifa_count--;
|
||||
vrf->total_ifa_count--;
|
||||
LIST_REMOVE(sctp_ifap, next_bucket);
|
||||
LIST_REMOVE(sctp_ifap, next_ifa);
|
||||
atomic_add_int(&sctp_ifnp->refcount, -1);
|
||||
} else {
|
||||
|
@ -112,9 +112,11 @@ TAILQ_HEAD(sctp_streamhead, sctp_stream_queue_pending);
|
||||
|
||||
struct sctp_vrf {
|
||||
LIST_ENTRY(sctp_vrf) next_vrf;
|
||||
struct sctp_ifalist *vrf_addr_hash;
|
||||
struct sctp_ifnlist ifnlist;
|
||||
uint32_t vrf_id;
|
||||
uint32_t total_ifa_count;
|
||||
u_long vrf_hashmark;
|
||||
};
|
||||
|
||||
struct sctp_ifn {
|
||||
@ -144,6 +146,7 @@ struct sctp_ifn {
|
||||
|
||||
struct sctp_ifa {
|
||||
LIST_ENTRY(sctp_ifa) next_ifa;
|
||||
LIST_ENTRY(sctp_ifa) next_bucket;
|
||||
struct sctp_ifn *ifn_p; /* back pointer to parent ifn */
|
||||
void *ifa; /* pointer to ifa, needed for flag update for
|
||||
* that we MUST lock appropriate locks. This
|
||||
|
@ -4271,26 +4271,68 @@ sctp_find_ifa_in_ifn(struct sctp_ifn *sctp_ifnp, struct sockaddr *addr,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
sctp_get_ifa_hash_val(struct sockaddr *addr)
|
||||
{
|
||||
|
||||
if (addr->sa_family == AF_INET) {
|
||||
struct sockaddr_in *sin;
|
||||
|
||||
sin = (struct sockaddr_in *)addr;
|
||||
return (sin->sin_addr.s_addr ^ (sin->sin_addr.s_addr >> 16));
|
||||
} else if (addr->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
uint32_t hash_of_addr;
|
||||
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
hash_of_addr = (sin6->sin6_addr.s6_addr32[0] +
|
||||
sin6->sin6_addr.s6_addr32[1] +
|
||||
sin6->sin6_addr.s6_addr32[2] +
|
||||
sin6->sin6_addr.s6_addr32[3]);
|
||||
hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16));
|
||||
return (hash_of_addr);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct sctp_ifa *
|
||||
sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
|
||||
{
|
||||
struct sctp_ifa *sctp_ifap;
|
||||
struct sctp_ifn *sctp_ifnp = NULL;
|
||||
struct sctp_vrf *vrf;
|
||||
struct sctp_ifalist *hash_head;
|
||||
uint32_t hash_of_addr;
|
||||
|
||||
vrf = sctp_find_vrf(vrf_id);
|
||||
if (vrf == NULL)
|
||||
return (NULL);
|
||||
|
||||
hash_of_addr = sctp_get_ifa_hash_val(addr);
|
||||
if (holds_lock == 0)
|
||||
SCTP_IPI_ADDR_LOCK();
|
||||
|
||||
LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
|
||||
sctp_ifap = sctp_find_ifa_in_ifn(sctp_ifnp, addr, 1);
|
||||
if (sctp_ifap) {
|
||||
if (holds_lock == 0)
|
||||
SCTP_IPI_ADDR_UNLOCK();
|
||||
return (sctp_ifap);
|
||||
hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_hashmark)];
|
||||
LIST_FOREACH(sctp_ifap, hash_head, next_bucket) {
|
||||
if (addr->sa_family != sctp_ifap->address.sa.sa_family)
|
||||
continue;
|
||||
if (addr->sa_family == AF_INET) {
|
||||
if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
|
||||
sctp_ifap->address.sin.sin_addr.s_addr) {
|
||||
/* found him. */
|
||||
if (holds_lock == 0)
|
||||
SCTP_IPI_ADDR_UNLOCK();
|
||||
return (sctp_ifap);
|
||||
break;
|
||||
}
|
||||
} else if (addr->sa_family == AF_INET6) {
|
||||
if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr,
|
||||
&sctp_ifap->address.sin6.sin6_addr)) {
|
||||
/* found him. */
|
||||
if (holds_lock == 0)
|
||||
SCTP_IPI_ADDR_UNLOCK();
|
||||
return (sctp_ifap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (holds_lock == 0)
|
||||
|
@ -56,6 +56,9 @@ void sctp_m_freem(struct mbuf *m);
|
||||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
uint32_t
|
||||
sctp_get_ifa_hash_val(struct sockaddr *addr);
|
||||
|
||||
struct sctp_ifa *
|
||||
sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, int hold_lock);
|
||||
struct sctp_ifa *
|
||||
|
Loading…
Reference in New Issue
Block a user