Changeset View
Changeset View
Standalone View
Standalone View
sys/netpfil/ipfw/ip_fw_table_algo.c
Show First 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/rwlock.h> | #include <sys/rwlock.h> | ||||
#include <sys/rmlock.h> | #include <sys/rmlock.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/queue.h> | #include <sys/queue.h> | ||||
#include <net/ethernet.h> | |||||
#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */ | #include <net/if.h> /* ip_fw.h requires IFNAMSIZ */ | ||||
#include <net/radix.h> | #include <net/radix.h> | ||||
#include <net/route.h> | #include <net/route.h> | ||||
#include <net/route/nhop.h> | #include <net/route/nhop.h> | ||||
#include <net/route/route_ctl.h> | #include <net/route/route_ctl.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/in_fib.h> | #include <netinet/in_fib.h> | ||||
▲ Show 20 Lines • Show All 251 Lines • ▼ Show 20 Lines | |||||
* is called with the offset in bits of the lookup key within the | * is called with the offset in bits of the lookup key within the | ||||
* array. If we use a sockaddr_in as the underlying type, | * array. If we use a sockaddr_in as the underlying type, | ||||
* sin_len is conveniently located at offset 0, sin_addr is at | * sin_len is conveniently located at offset 0, sin_addr is at | ||||
* offset 4 and normally aligned. | * offset 4 and normally aligned. | ||||
* But for portability, let's avoid assumption and make the code explicit | * But for portability, let's avoid assumption and make the code explicit | ||||
*/ | */ | ||||
#define KEY_LEN(v) *((uint8_t *)&(v)) | #define KEY_LEN(v) *((uint8_t *)&(v)) | ||||
/* | /* | ||||
* Do not require radix to compare more than actual IPv4/IPv6 address | * Do not require radix to compare more than actual IPv4/IPv6/MAC address | ||||
*/ | */ | ||||
#define KEY_LEN_INET (offsetof(struct sockaddr_in, sin_addr) + sizeof(in_addr_t)) | #define KEY_LEN_INET (offsetof(struct sockaddr_in, sin_addr) + sizeof(in_addr_t)) | ||||
#define KEY_LEN_INET6 (offsetof(struct sa_in6, sin6_addr) + sizeof(struct in6_addr)) | #define KEY_LEN_INET6 (offsetof(struct sa_in6, sin6_addr) + sizeof(struct in6_addr)) | ||||
#define KEY_LEN_MAC (offsetof(struct sa_mac, mac_addr) + ETHER_ADDR_LEN) | |||||
#define OFF_LEN_INET (8 * offsetof(struct sockaddr_in, sin_addr)) | #define OFF_LEN_INET (8 * offsetof(struct sockaddr_in, sin_addr)) | ||||
#define OFF_LEN_INET6 (8 * offsetof(struct sa_in6, sin6_addr)) | #define OFF_LEN_INET6 (8 * offsetof(struct sa_in6, sin6_addr)) | ||||
#define OFF_LEN_MAC (8 * offsetof(struct sa_mac, mac_addr)) | |||||
struct radix_addr_entry { | struct addr_radix_entry { | ||||
struct radix_node rn[2]; | struct radix_node rn[2]; | ||||
struct sockaddr_in addr; | struct sockaddr_in addr; | ||||
uint32_t value; | uint32_t value; | ||||
uint8_t masklen; | uint8_t masklen; | ||||
}; | }; | ||||
struct sa_in6 { | struct sa_in6 { | ||||
uint8_t sin6_len; | uint8_t sin6_len; | ||||
uint8_t sin6_family; | uint8_t sin6_family; | ||||
uint8_t pad[2]; | uint8_t pad[2]; | ||||
struct in6_addr sin6_addr; | struct in6_addr sin6_addr; | ||||
}; | }; | ||||
struct radix_addr_xentry { | struct addr_radix_xentry { | ||||
struct radix_node rn[2]; | struct radix_node rn[2]; | ||||
struct sa_in6 addr6; | struct sa_in6 addr6; | ||||
uint32_t value; | uint32_t value; | ||||
uint8_t masklen; | uint8_t masklen; | ||||
}; | }; | ||||
struct radix_cfg { | struct addr_radix_cfg { | ||||
struct radix_node_head *head4; | struct radix_node_head *head4; | ||||
struct radix_node_head *head6; | struct radix_node_head *head6; | ||||
size_t count4; | size_t count4; | ||||
size_t count6; | size_t count6; | ||||
}; | }; | ||||
struct sa_mac { | |||||
uint8_t mac_len; | |||||
struct ether_addr mac_addr; | |||||
melifaro: Worth naming the fields according to other SA-like structures (`mac_len`, `mac_addr`).
Also… | |||||
}; | |||||
struct ta_buf_radix | struct ta_buf_radix | ||||
{ | { | ||||
void *ent_ptr; | void *ent_ptr; | ||||
struct sockaddr *addr_ptr; | struct sockaddr *addr_ptr; | ||||
struct sockaddr *mask_ptr; | struct sockaddr *mask_ptr; | ||||
union { | union { | ||||
struct { | struct { | ||||
struct sockaddr_in sa; | struct sockaddr_in sa; | ||||
struct sockaddr_in ma; | struct sockaddr_in ma; | ||||
} a4; | } a4; | ||||
struct { | struct { | ||||
struct sa_in6 sa; | struct sa_in6 sa; | ||||
struct sa_in6 ma; | struct sa_in6 ma; | ||||
} a6; | } a6; | ||||
struct { | |||||
struct sa_mac sa; | |||||
struct sa_mac ma; | |||||
} mac; | |||||
} addr; | } addr; | ||||
}; | }; | ||||
static int ta_lookup_radix(struct table_info *ti, void *key, uint32_t keylen, | static int ta_lookup_addr_radix(struct table_info *ti, void *key, uint32_t keylen, | ||||
Done Inline ActionsCould you please explain why those renamings are required? melifaro: Could you please explain why those renamings are required? | |||||
Done Inline Actionsaddr_radix functions are used in addr:radix tables, mac_radix functions are used in mac:radix tables, just radix are used in both. smalukav_gmail.com: addr_radix functions are used in addr:radix tables, mac_radix functions are used in mac:radix… | |||||
uint32_t *val); | uint32_t *val); | ||||
static int ta_init_radix(struct ip_fw_chain *ch, void **ta_state, | static int ta_init_addr_radix(struct ip_fw_chain *ch, void **ta_state, | ||||
struct table_info *ti, char *data, uint8_t tflags); | struct table_info *ti, char *data, uint8_t tflags); | ||||
static int flush_radix_entry(struct radix_node *rn, void *arg); | static int flush_radix_entry(struct radix_node *rn, void *arg); | ||||
static void ta_destroy_radix(void *ta_state, struct table_info *ti); | static void ta_destroy_addr_radix(void *ta_state, struct table_info *ti); | ||||
static void ta_dump_radix_tinfo(void *ta_state, struct table_info *ti, | static void ta_dump_addr_radix_tinfo(void *ta_state, struct table_info *ti, | ||||
ipfw_ta_tinfo *tinfo); | ipfw_ta_tinfo *tinfo); | ||||
static int ta_dump_radix_tentry(void *ta_state, struct table_info *ti, | static int ta_dump_addr_radix_tentry(void *ta_state, struct table_info *ti, | ||||
void *e, ipfw_obj_tentry *tent); | void *e, ipfw_obj_tentry *tent); | ||||
static int ta_find_radix_tentry(void *ta_state, struct table_info *ti, | static int ta_find_addr_radix_tentry(void *ta_state, struct table_info *ti, | ||||
ipfw_obj_tentry *tent); | ipfw_obj_tentry *tent); | ||||
static void ta_foreach_radix(void *ta_state, struct table_info *ti, | static void ta_foreach_addr_radix(void *ta_state, struct table_info *ti, | ||||
ta_foreach_f *f, void *arg); | ta_foreach_f *f, void *arg); | ||||
static void tei_to_sockaddr_ent(struct tentry_info *tei, struct sockaddr *sa, | static void tei_to_sockaddr_ent_addr(struct tentry_info *tei, struct sockaddr *sa, | ||||
struct sockaddr *ma, int *set_mask); | struct sockaddr *ma, int *set_mask); | ||||
static int ta_prepare_add_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | static int ta_prepare_add_addr_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | ||||
void *ta_buf); | void *ta_buf); | ||||
static int ta_add_radix(void *ta_state, struct table_info *ti, | static int ta_add_addr_radix(void *ta_state, struct table_info *ti, | ||||
struct tentry_info *tei, void *ta_buf, uint32_t *pnum); | struct tentry_info *tei, void *ta_buf, uint32_t *pnum); | ||||
static int ta_prepare_del_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | static int ta_prepare_del_addr_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | ||||
void *ta_buf); | void *ta_buf); | ||||
static int ta_del_radix(void *ta_state, struct table_info *ti, | static int ta_del_addr_radix(void *ta_state, struct table_info *ti, | ||||
struct tentry_info *tei, void *ta_buf, uint32_t *pnum); | struct tentry_info *tei, void *ta_buf, uint32_t *pnum); | ||||
static void ta_flush_radix_entry(struct ip_fw_chain *ch, struct tentry_info *tei, | static void ta_flush_radix_entry(struct ip_fw_chain *ch, struct tentry_info *tei, | ||||
void *ta_buf); | void *ta_buf); | ||||
static int ta_need_modify_radix(void *ta_state, struct table_info *ti, | static int ta_need_modify_radix(void *ta_state, struct table_info *ti, | ||||
uint32_t count, uint64_t *pflags); | uint32_t count, uint64_t *pflags); | ||||
static int | static int | ||||
ta_lookup_radix(struct table_info *ti, void *key, uint32_t keylen, | ta_lookup_addr_radix(struct table_info *ti, void *key, uint32_t keylen, | ||||
uint32_t *val) | uint32_t *val) | ||||
{ | { | ||||
struct radix_node_head *rnh; | struct radix_node_head *rnh; | ||||
if (keylen == sizeof(in_addr_t)) { | if (keylen == sizeof(in_addr_t)) { | ||||
struct radix_addr_entry *ent; | struct addr_radix_entry *ent; | ||||
struct sockaddr_in sa; | struct sockaddr_in sa; | ||||
KEY_LEN(sa) = KEY_LEN_INET; | KEY_LEN(sa) = KEY_LEN_INET; | ||||
sa.sin_addr.s_addr = *((in_addr_t *)key); | sa.sin_addr.s_addr = *((in_addr_t *)key); | ||||
rnh = (struct radix_node_head *)ti->state; | rnh = (struct radix_node_head *)ti->state; | ||||
ent = (struct radix_addr_entry *)(rnh->rnh_matchaddr(&sa, &rnh->rh)); | ent = (struct addr_radix_entry *)(rnh->rnh_matchaddr(&sa, &rnh->rh)); | ||||
if (ent != NULL) { | if (ent != NULL) { | ||||
*val = ent->value; | *val = ent->value; | ||||
return (1); | return (1); | ||||
} | } | ||||
} else { | } else if (keylen == sizeof(struct in6_addr)) { | ||||
struct radix_addr_xentry *xent; | struct addr_radix_xentry *xent; | ||||
struct sa_in6 sa6; | struct sa_in6 sa6; | ||||
KEY_LEN(sa6) = KEY_LEN_INET6; | KEY_LEN(sa6) = KEY_LEN_INET6; | ||||
memcpy(&sa6.sin6_addr, key, sizeof(struct in6_addr)); | memcpy(&sa6.sin6_addr, key, sizeof(struct in6_addr)); | ||||
rnh = (struct radix_node_head *)ti->xstate; | rnh = (struct radix_node_head *)ti->xstate; | ||||
xent = (struct radix_addr_xentry *)(rnh->rnh_matchaddr(&sa6, &rnh->rh)); | xent = (struct addr_radix_xentry *)(rnh->rnh_matchaddr(&sa6, &rnh->rh)); | ||||
if (xent != NULL) { | if (xent != NULL) { | ||||
*val = xent->value; | *val = xent->value; | ||||
return (1); | return (1); | ||||
} | } | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* New table | * New table | ||||
*/ | */ | ||||
static int | static int | ||||
ta_init_radix(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti, | ta_init_addr_radix(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti, | ||||
char *data, uint8_t tflags) | char *data, uint8_t tflags) | ||||
{ | { | ||||
struct radix_cfg *cfg; | struct addr_radix_cfg *cfg; | ||||
if (!rn_inithead(&ti->state, OFF_LEN_INET)) | if (!rn_inithead(&ti->state, OFF_LEN_INET)) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
if (!rn_inithead(&ti->xstate, OFF_LEN_INET6)) { | if (!rn_inithead(&ti->xstate, OFF_LEN_INET6)) { | ||||
rn_detachhead(&ti->state); | rn_detachhead(&ti->state); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
cfg = malloc(sizeof(struct radix_cfg), M_IPFW, M_WAITOK | M_ZERO); | cfg = malloc(sizeof(struct addr_radix_cfg), M_IPFW, M_WAITOK | M_ZERO); | ||||
*ta_state = cfg; | *ta_state = cfg; | ||||
ti->lookup = ta_lookup_radix; | ti->lookup = ta_lookup_addr_radix; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
flush_radix_entry(struct radix_node *rn, void *arg) | flush_radix_entry(struct radix_node *rn, void *arg) | ||||
{ | { | ||||
struct radix_node_head * const rnh = arg; | struct radix_node_head * const rnh = arg; | ||||
struct radix_addr_entry *ent; | struct addr_radix_entry *ent; | ||||
ent = (struct radix_addr_entry *) | ent = (struct addr_radix_entry *) | ||||
rnh->rnh_deladdr(rn->rn_key, rn->rn_mask, &rnh->rh); | rnh->rnh_deladdr(rn->rn_key, rn->rn_mask, &rnh->rh); | ||||
if (ent != NULL) | if (ent != NULL) | ||||
free(ent, M_IPFW_TBL); | free(ent, M_IPFW_TBL); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
ta_destroy_radix(void *ta_state, struct table_info *ti) | ta_destroy_addr_radix(void *ta_state, struct table_info *ti) | ||||
{ | { | ||||
struct radix_cfg *cfg; | struct addr_radix_cfg *cfg; | ||||
struct radix_node_head *rnh; | struct radix_node_head *rnh; | ||||
cfg = (struct radix_cfg *)ta_state; | cfg = (struct addr_radix_cfg *)ta_state; | ||||
rnh = (struct radix_node_head *)(ti->state); | rnh = (struct radix_node_head *)(ti->state); | ||||
rnh->rnh_walktree(&rnh->rh, flush_radix_entry, rnh); | rnh->rnh_walktree(&rnh->rh, flush_radix_entry, rnh); | ||||
rn_detachhead(&ti->state); | rn_detachhead(&ti->state); | ||||
rnh = (struct radix_node_head *)(ti->xstate); | rnh = (struct radix_node_head *)(ti->xstate); | ||||
rnh->rnh_walktree(&rnh->rh, flush_radix_entry, rnh); | rnh->rnh_walktree(&rnh->rh, flush_radix_entry, rnh); | ||||
rn_detachhead(&ti->xstate); | rn_detachhead(&ti->xstate); | ||||
free(cfg, M_IPFW); | free(cfg, M_IPFW); | ||||
} | } | ||||
/* | /* | ||||
* Provide algo-specific table info | * Provide algo-specific table info | ||||
*/ | */ | ||||
static void | static void | ||||
ta_dump_radix_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo) | ta_dump_addr_radix_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo) | ||||
{ | { | ||||
struct radix_cfg *cfg; | struct addr_radix_cfg *cfg; | ||||
cfg = (struct radix_cfg *)ta_state; | cfg = (struct addr_radix_cfg *)ta_state; | ||||
tinfo->flags = IPFW_TATFLAGS_AFDATA | IPFW_TATFLAGS_AFITEM; | tinfo->flags = IPFW_TATFLAGS_AFDATA | IPFW_TATFLAGS_AFITEM; | ||||
tinfo->taclass4 = IPFW_TACLASS_RADIX; | tinfo->taclass4 = IPFW_TACLASS_RADIX; | ||||
tinfo->count4 = cfg->count4; | tinfo->count4 = cfg->count4; | ||||
tinfo->itemsize4 = sizeof(struct radix_addr_entry); | tinfo->itemsize4 = sizeof(struct addr_radix_entry); | ||||
tinfo->taclass6 = IPFW_TACLASS_RADIX; | tinfo->taclass6 = IPFW_TACLASS_RADIX; | ||||
tinfo->count6 = cfg->count6; | tinfo->count6 = cfg->count6; | ||||
tinfo->itemsize6 = sizeof(struct radix_addr_xentry); | tinfo->itemsize6 = sizeof(struct addr_radix_xentry); | ||||
} | } | ||||
static int | static int | ||||
ta_dump_radix_tentry(void *ta_state, struct table_info *ti, void *e, | ta_dump_addr_radix_tentry(void *ta_state, struct table_info *ti, void *e, | ||||
ipfw_obj_tentry *tent) | ipfw_obj_tentry *tent) | ||||
{ | { | ||||
struct radix_addr_entry *n; | struct addr_radix_entry *n; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
struct radix_addr_xentry *xn; | struct addr_radix_xentry *xn; | ||||
#endif | #endif | ||||
n = (struct radix_addr_entry *)e; | n = (struct addr_radix_entry *)e; | ||||
/* Guess IPv4/IPv6 radix by sockaddr family */ | /* Guess IPv4/IPv6 radix by sockaddr family */ | ||||
if (n->addr.sin_family == AF_INET) { | if (n->addr.sin_family == AF_INET) { | ||||
tent->k.addr.s_addr = n->addr.sin_addr.s_addr; | tent->k.addr.s_addr = n->addr.sin_addr.s_addr; | ||||
tent->masklen = n->masklen; | tent->masklen = n->masklen; | ||||
tent->subtype = AF_INET; | tent->subtype = AF_INET; | ||||
tent->v.kidx = n->value; | tent->v.kidx = n->value; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
} else { | } else { | ||||
xn = (struct radix_addr_xentry *)e; | xn = (struct addr_radix_xentry *)e; | ||||
memcpy(&tent->k.addr6, &xn->addr6.sin6_addr, | memcpy(&tent->k.addr6, &xn->addr6.sin6_addr, | ||||
sizeof(struct in6_addr)); | sizeof(struct in6_addr)); | ||||
tent->masklen = xn->masklen; | tent->masklen = xn->masklen; | ||||
tent->subtype = AF_INET6; | tent->subtype = AF_INET6; | ||||
tent->v.kidx = xn->value; | tent->v.kidx = xn->value; | ||||
#endif | #endif | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ta_find_radix_tentry(void *ta_state, struct table_info *ti, | ta_find_addr_radix_tentry(void *ta_state, struct table_info *ti, | ||||
ipfw_obj_tentry *tent) | ipfw_obj_tentry *tent) | ||||
{ | { | ||||
struct radix_node_head *rnh; | struct radix_node_head *rnh; | ||||
void *e; | void *e; | ||||
e = NULL; | e = NULL; | ||||
if (tent->subtype == AF_INET) { | if (tent->subtype == AF_INET) { | ||||
struct sockaddr_in sa; | struct sockaddr_in sa; | ||||
KEY_LEN(sa) = KEY_LEN_INET; | KEY_LEN(sa) = KEY_LEN_INET; | ||||
sa.sin_addr.s_addr = tent->k.addr.s_addr; | sa.sin_addr.s_addr = tent->k.addr.s_addr; | ||||
rnh = (struct radix_node_head *)ti->state; | rnh = (struct radix_node_head *)ti->state; | ||||
e = rnh->rnh_matchaddr(&sa, &rnh->rh); | e = rnh->rnh_matchaddr(&sa, &rnh->rh); | ||||
} else { | } else if (tent->subtype == AF_INET6) { | ||||
struct sa_in6 sa6; | struct sa_in6 sa6; | ||||
KEY_LEN(sa6) = KEY_LEN_INET6; | KEY_LEN(sa6) = KEY_LEN_INET6; | ||||
memcpy(&sa6.sin6_addr, &tent->k.addr6, sizeof(struct in6_addr)); | memcpy(&sa6.sin6_addr, &tent->k.addr6, sizeof(struct in6_addr)); | ||||
rnh = (struct radix_node_head *)ti->xstate; | rnh = (struct radix_node_head *)ti->xstate; | ||||
e = rnh->rnh_matchaddr(&sa6, &rnh->rh); | e = rnh->rnh_matchaddr(&sa6, &rnh->rh); | ||||
} | } | ||||
if (e != NULL) { | if (e != NULL) { | ||||
ta_dump_radix_tentry(ta_state, ti, e, tent); | ta_dump_addr_radix_tentry(ta_state, ti, e, tent); | ||||
return (0); | return (0); | ||||
} | } | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
static void | static void | ||||
ta_foreach_radix(void *ta_state, struct table_info *ti, ta_foreach_f *f, | ta_foreach_addr_radix(void *ta_state, struct table_info *ti, ta_foreach_f *f, | ||||
void *arg) | void *arg) | ||||
{ | { | ||||
struct radix_node_head *rnh; | struct radix_node_head *rnh; | ||||
rnh = (struct radix_node_head *)(ti->state); | rnh = (struct radix_node_head *)(ti->state); | ||||
rnh->rnh_walktree(&rnh->rh, (walktree_f_t *)f, arg); | rnh->rnh_walktree(&rnh->rh, (walktree_f_t *)f, arg); | ||||
rnh = (struct radix_node_head *)(ti->xstate); | rnh = (struct radix_node_head *)(ti->xstate); | ||||
Show All 11 Lines | ipv6_writemask(struct in6_addr *addr6, uint8_t mask) | ||||
for (cp = (uint32_t *)addr6; mask >= 32; mask -= 32) | for (cp = (uint32_t *)addr6; mask >= 32; mask -= 32) | ||||
*cp++ = 0xFFFFFFFF; | *cp++ = 0xFFFFFFFF; | ||||
if (mask > 0) | if (mask > 0) | ||||
*cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0); | *cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0); | ||||
} | } | ||||
#endif | #endif | ||||
static void | static void | ||||
tei_to_sockaddr_ent(struct tentry_info *tei, struct sockaddr *sa, | tei_to_sockaddr_ent_addr(struct tentry_info *tei, struct sockaddr *sa, | ||||
struct sockaddr *ma, int *set_mask) | struct sockaddr *ma, int *set_mask) | ||||
{ | { | ||||
int mlen; | int mlen; | ||||
#ifdef INET | #ifdef INET | ||||
struct sockaddr_in *addr, *mask; | struct sockaddr_in *addr, *mask; | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
struct sa_in6 *addr6, *mask6; | struct sa_in6 *addr6, *mask6; | ||||
Show All 35 Lines | if (mlen != 128) | ||||
*set_mask = 1; | *set_mask = 1; | ||||
else | else | ||||
*set_mask = 0; | *set_mask = 0; | ||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
ta_prepare_add_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | ta_prepare_add_addr_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | ||||
void *ta_buf) | void *ta_buf) | ||||
{ | { | ||||
struct ta_buf_radix *tb; | struct ta_buf_radix *tb; | ||||
struct radix_addr_entry *ent; | struct addr_radix_entry *ent; | ||||
#ifdef INET6 | #ifdef INET6 | ||||
struct radix_addr_xentry *xent; | struct addr_radix_xentry *xent; | ||||
#endif | #endif | ||||
struct sockaddr *addr, *mask; | struct sockaddr *addr, *mask; | ||||
int mlen, set_mask; | int mlen, set_mask; | ||||
tb = (struct ta_buf_radix *)ta_buf; | tb = (struct ta_buf_radix *)ta_buf; | ||||
mlen = tei->masklen; | mlen = tei->masklen; | ||||
set_mask = 0; | set_mask = 0; | ||||
Show All 21 Lines | #ifdef INET6 | ||||
mask = (struct sockaddr *)&tb->addr.a6.ma; | mask = (struct sockaddr *)&tb->addr.a6.ma; | ||||
tb->ent_ptr = xent; | tb->ent_ptr = xent; | ||||
#endif | #endif | ||||
} else { | } else { | ||||
/* Unknown CIDR type */ | /* Unknown CIDR type */ | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
tei_to_sockaddr_ent(tei, addr, mask, &set_mask); | tei_to_sockaddr_ent_addr(tei, addr, mask, &set_mask); | ||||
/* Set pointers */ | /* Set pointers */ | ||||
tb->addr_ptr = addr; | tb->addr_ptr = addr; | ||||
if (set_mask != 0) | if (set_mask != 0) | ||||
tb->mask_ptr = mask; | tb->mask_ptr = mask; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ta_add_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei, | ta_add_addr_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei, | ||||
void *ta_buf, uint32_t *pnum) | void *ta_buf, uint32_t *pnum) | ||||
{ | { | ||||
struct radix_cfg *cfg; | struct addr_radix_cfg *cfg; | ||||
struct radix_node_head *rnh; | struct radix_node_head *rnh; | ||||
struct radix_node *rn; | struct radix_node *rn; | ||||
struct ta_buf_radix *tb; | struct ta_buf_radix *tb; | ||||
uint32_t *old_value, value; | uint32_t *old_value, value; | ||||
cfg = (struct radix_cfg *)ta_state; | cfg = (struct addr_radix_cfg *)ta_state; | ||||
tb = (struct ta_buf_radix *)ta_buf; | tb = (struct ta_buf_radix *)ta_buf; | ||||
/* Save current entry value from @tei */ | /* Save current entry value from @tei */ | ||||
if (tei->subtype == AF_INET) { | if (tei->subtype == AF_INET) { | ||||
rnh = ti->state; | rnh = ti->state; | ||||
((struct radix_addr_entry *)tb->ent_ptr)->value = tei->value; | ((struct addr_radix_entry *)tb->ent_ptr)->value = tei->value; | ||||
} else { | } else { | ||||
rnh = ti->xstate; | rnh = ti->xstate; | ||||
((struct radix_addr_xentry *)tb->ent_ptr)->value = tei->value; | ((struct addr_radix_xentry *)tb->ent_ptr)->value = tei->value; | ||||
} | } | ||||
/* Search for an entry first */ | /* Search for an entry first */ | ||||
rn = rnh->rnh_lookup(tb->addr_ptr, tb->mask_ptr, &rnh->rh); | rn = rnh->rnh_lookup(tb->addr_ptr, tb->mask_ptr, &rnh->rh); | ||||
if (rn != NULL) { | if (rn != NULL) { | ||||
if ((tei->flags & TEI_FLAGS_UPDATE) == 0) | if ((tei->flags & TEI_FLAGS_UPDATE) == 0) | ||||
return (EEXIST); | return (EEXIST); | ||||
/* Record already exists. Update value if we're asked to */ | /* Record already exists. Update value if we're asked to */ | ||||
if (tei->subtype == AF_INET) | if (tei->subtype == AF_INET) | ||||
old_value = &((struct radix_addr_entry *)rn)->value; | old_value = &((struct addr_radix_entry *)rn)->value; | ||||
else | else | ||||
old_value = &((struct radix_addr_xentry *)rn)->value; | old_value = &((struct addr_radix_xentry *)rn)->value; | ||||
value = *old_value; | value = *old_value; | ||||
*old_value = tei->value; | *old_value = tei->value; | ||||
tei->value = value; | tei->value = value; | ||||
/* Indicate that update has happened instead of addition */ | /* Indicate that update has happened instead of addition */ | ||||
tei->flags |= TEI_FLAGS_UPDATED; | tei->flags |= TEI_FLAGS_UPDATED; | ||||
*pnum = 0; | *pnum = 0; | ||||
Show All 16 Lines | else | ||||
cfg->count6++; | cfg->count6++; | ||||
tb->ent_ptr = NULL; | tb->ent_ptr = NULL; | ||||
*pnum = 1; | *pnum = 1; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ta_prepare_del_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | ta_prepare_del_addr_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | ||||
void *ta_buf) | void *ta_buf) | ||||
{ | { | ||||
struct ta_buf_radix *tb; | struct ta_buf_radix *tb; | ||||
struct sockaddr *addr, *mask; | struct sockaddr *addr, *mask; | ||||
int mlen, set_mask; | int mlen, set_mask; | ||||
tb = (struct ta_buf_radix *)ta_buf; | tb = (struct ta_buf_radix *)ta_buf; | ||||
Show All 12 Lines | if (mlen > 128) | ||||
return (EINVAL); | return (EINVAL); | ||||
addr = (struct sockaddr *)&tb->addr.a6.sa; | addr = (struct sockaddr *)&tb->addr.a6.sa; | ||||
mask = (struct sockaddr *)&tb->addr.a6.ma; | mask = (struct sockaddr *)&tb->addr.a6.ma; | ||||
#endif | #endif | ||||
} else | } else | ||||
return (EINVAL); | return (EINVAL); | ||||
tei_to_sockaddr_ent(tei, addr, mask, &set_mask); | tei_to_sockaddr_ent_addr(tei, addr, mask, &set_mask); | ||||
tb->addr_ptr = addr; | tb->addr_ptr = addr; | ||||
if (set_mask != 0) | if (set_mask != 0) | ||||
tb->mask_ptr = mask; | tb->mask_ptr = mask; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
ta_del_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei, | ta_del_addr_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei, | ||||
void *ta_buf, uint32_t *pnum) | void *ta_buf, uint32_t *pnum) | ||||
{ | { | ||||
struct radix_cfg *cfg; | struct addr_radix_cfg *cfg; | ||||
struct radix_node_head *rnh; | struct radix_node_head *rnh; | ||||
struct radix_node *rn; | struct radix_node *rn; | ||||
struct ta_buf_radix *tb; | struct ta_buf_radix *tb; | ||||
cfg = (struct radix_cfg *)ta_state; | cfg = (struct addr_radix_cfg *)ta_state; | ||||
tb = (struct ta_buf_radix *)ta_buf; | tb = (struct ta_buf_radix *)ta_buf; | ||||
if (tei->subtype == AF_INET) | if (tei->subtype == AF_INET) | ||||
rnh = ti->state; | rnh = ti->state; | ||||
else | else | ||||
rnh = ti->xstate; | rnh = ti->xstate; | ||||
rn = rnh->rnh_deladdr(tb->addr_ptr, tb->mask_ptr, &rnh->rh); | rn = rnh->rnh_deladdr(tb->addr_ptr, tb->mask_ptr, &rnh->rh); | ||||
if (rn == NULL) | if (rn == NULL) | ||||
return (ENOENT); | return (ENOENT); | ||||
/* Save entry value to @tei */ | /* Save entry value to @tei */ | ||||
if (tei->subtype == AF_INET) | if (tei->subtype == AF_INET) | ||||
tei->value = ((struct radix_addr_entry *)rn)->value; | tei->value = ((struct addr_radix_entry *)rn)->value; | ||||
else | else | ||||
tei->value = ((struct radix_addr_xentry *)rn)->value; | tei->value = ((struct addr_radix_xentry *)rn)->value; | ||||
tb->ent_ptr = rn; | tb->ent_ptr = rn; | ||||
if (tei->subtype == AF_INET) | if (tei->subtype == AF_INET) | ||||
cfg->count4--; | cfg->count4--; | ||||
else | else | ||||
cfg->count6--; | cfg->count6--; | ||||
*pnum = 1; | *pnum = 1; | ||||
Show All 27 Lines | ta_need_modify_radix(void *ta_state, struct table_info *ti, uint32_t count, | ||||
return (0); | return (0); | ||||
} | } | ||||
struct table_algo addr_radix = { | struct table_algo addr_radix = { | ||||
.name = "addr:radix", | .name = "addr:radix", | ||||
.type = IPFW_TABLE_ADDR, | .type = IPFW_TABLE_ADDR, | ||||
.flags = TA_FLAG_DEFAULT, | .flags = TA_FLAG_DEFAULT, | ||||
.ta_buf_size = sizeof(struct ta_buf_radix), | .ta_buf_size = sizeof(struct ta_buf_radix), | ||||
.init = ta_init_radix, | .init = ta_init_addr_radix, | ||||
.destroy = ta_destroy_radix, | .destroy = ta_destroy_addr_radix, | ||||
.prepare_add = ta_prepare_add_radix, | .prepare_add = ta_prepare_add_addr_radix, | ||||
.prepare_del = ta_prepare_del_radix, | .prepare_del = ta_prepare_del_addr_radix, | ||||
.add = ta_add_radix, | .add = ta_add_addr_radix, | ||||
.del = ta_del_radix, | .del = ta_del_addr_radix, | ||||
.flush_entry = ta_flush_radix_entry, | .flush_entry = ta_flush_radix_entry, | ||||
.foreach = ta_foreach_radix, | .foreach = ta_foreach_addr_radix, | ||||
.dump_tentry = ta_dump_radix_tentry, | .dump_tentry = ta_dump_addr_radix_tentry, | ||||
.find_tentry = ta_find_radix_tentry, | .find_tentry = ta_find_addr_radix_tentry, | ||||
.dump_tinfo = ta_dump_radix_tinfo, | .dump_tinfo = ta_dump_addr_radix_tinfo, | ||||
.need_modify = ta_need_modify_radix, | .need_modify = ta_need_modify_radix, | ||||
}; | }; | ||||
/* | /* | ||||
* addr:hash cmds | * addr:hash cmds | ||||
* | * | ||||
* | * | ||||
* ti->data: | * ti->data: | ||||
▲ Show 20 Lines • Show All 3,108 Lines • ▼ Show 20 Lines | struct table_algo addr_kfib = { | ||||
.destroy = ta_destroy_kfib, | .destroy = ta_destroy_kfib, | ||||
.foreach = ta_foreach_kfib, | .foreach = ta_foreach_kfib, | ||||
.dump_tentry = ta_dump_kfib_tentry, | .dump_tentry = ta_dump_kfib_tentry, | ||||
.find_tentry = ta_find_kfib_tentry, | .find_tentry = ta_find_kfib_tentry, | ||||
.dump_tinfo = ta_dump_kfib_tinfo, | .dump_tinfo = ta_dump_kfib_tinfo, | ||||
.print_config = ta_print_kfib_config, | .print_config = ta_print_kfib_config, | ||||
}; | }; | ||||
struct mac_radix_entry { | |||||
struct radix_node rn[2]; | |||||
uint32_t value; | |||||
uint8_t masklen; | |||||
struct sa_mac sa; | |||||
Done Inline ActionsWorth putting masklen into sa. melifaro: Worth putting masklen into sa. | |||||
}; | |||||
struct mac_radix_cfg { | |||||
struct radix_node_head *head; | |||||
size_t count; | |||||
}; | |||||
static int | |||||
ta_lookup_mac_radix(struct table_info *ti, void *key, uint32_t keylen, | |||||
uint32_t *val) | |||||
{ | |||||
struct radix_node_head *rnh; | |||||
if (keylen == ETHER_ADDR_LEN) { | |||||
Done Inline ActionsAre there other key lengths? There's a plenty of other places (such as KEY_LEN_MAC) where the length is already hardcoded. melifaro: Are there other key lengths? There's a plenty of other places (such as KEY_LEN_MAC) where the… | |||||
Done Inline ActionsThere can be in the future, for example, for InfiniBand address. I used the approach from IPv4 and IPv6 addresses. smalukav_gmail.com: There can be in the future, for example, for InfiniBand address. I used the approach from IPv4… | |||||
struct mac_radix_entry *ent; | |||||
struct sa_mac sa; | |||||
KEY_LEN(sa) = KEY_LEN_MAC; | |||||
memcpy(sa.mac_addr.octet, key, ETHER_ADDR_LEN); | |||||
rnh = (struct radix_node_head *)ti->state; | |||||
ent = (struct mac_radix_entry *)(rnh->rnh_matchaddr(&sa, &rnh->rh)); | |||||
if (ent != NULL) { | |||||
*val = ent->value; | |||||
return (1); | |||||
} | |||||
} | |||||
return (0); | |||||
} | |||||
static int | |||||
ta_init_mac_radix(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti, | |||||
char *data, uint8_t tflags) | |||||
{ | |||||
struct mac_radix_cfg *cfg; | |||||
if (!rn_inithead(&ti->state, OFF_LEN_MAC)) | |||||
return (ENOMEM); | |||||
cfg = malloc(sizeof(struct mac_radix_cfg), M_IPFW, M_WAITOK | M_ZERO); | |||||
*ta_state = cfg; | |||||
ti->lookup = ta_lookup_mac_radix; | |||||
return (0); | |||||
} | |||||
static void | |||||
ta_destroy_mac_radix(void *ta_state, struct table_info *ti) | |||||
{ | |||||
struct mac_radix_cfg *cfg; | |||||
struct radix_node_head *rnh; | |||||
cfg = (struct mac_radix_cfg *)ta_state; | |||||
rnh = (struct radix_node_head *)(ti->state); | |||||
rnh->rnh_walktree(&rnh->rh, flush_radix_entry, rnh); | |||||
rn_detachhead(&ti->state); | |||||
free(cfg, M_IPFW); | |||||
} | |||||
static void | |||||
tei_to_sockaddr_ent_mac(struct tentry_info *tei, struct sockaddr *sa, | |||||
struct sockaddr *ma, int *set_mask) | |||||
{ | |||||
int mlen, i; | |||||
struct sa_mac *addr, *mask; | |||||
u_char *cp; | |||||
mlen = tei->masklen; | |||||
addr = (struct sa_mac *)sa; | |||||
mask = (struct sa_mac *)ma; | |||||
/* Set 'total' structure length */ | |||||
KEY_LEN(*addr) = KEY_LEN_MAC; | |||||
KEY_LEN(*mask) = KEY_LEN_MAC; | |||||
for (i = mlen, cp = mask->mac_addr.octet; i >= 8; i -= 8) | |||||
*cp++ = 0xFF; | |||||
if (i > 0) | |||||
*cp = ~((1 << (8 - i)) - 1); | |||||
addr->mac_addr = *((struct ether_addr *)tei->paddr); | |||||
for (i = 0; i < ETHER_ADDR_LEN; ++i) | |||||
addr->mac_addr.octet[i] &= mask->mac_addr.octet[i]; | |||||
if (mlen != 8 * ETHER_ADDR_LEN) | |||||
*set_mask = 1; | |||||
else | |||||
*set_mask = 0; | |||||
} | |||||
static int | |||||
ta_prepare_add_mac_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | |||||
void *ta_buf) | |||||
{ | |||||
struct ta_buf_radix *tb; | |||||
struct mac_radix_entry *ent; | |||||
struct sockaddr *addr, *mask; | |||||
int mlen, set_mask; | |||||
tb = (struct ta_buf_radix *)ta_buf; | |||||
mlen = tei->masklen; | |||||
set_mask = 0; | |||||
if (tei->subtype == AF_LINK) { | |||||
if (mlen > 8 * ETHER_ADDR_LEN) | |||||
return (EINVAL); | |||||
ent = malloc(sizeof(*ent), M_IPFW_TBL, M_WAITOK | M_ZERO); | |||||
ent->masklen = mlen; | |||||
addr = (struct sockaddr *)&ent->sa; | |||||
mask = (struct sockaddr *)&tb->addr.mac.ma; | |||||
tb->ent_ptr = ent; | |||||
} else { | |||||
/* Unknown CIDR type */ | |||||
return (EINVAL); | |||||
} | |||||
tei_to_sockaddr_ent_mac(tei, addr, mask, &set_mask); | |||||
/* Set pointers */ | |||||
tb->addr_ptr = addr; | |||||
if (set_mask != 0) | |||||
tb->mask_ptr = mask; | |||||
return (0); | |||||
} | |||||
static int | |||||
ta_add_mac_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei, | |||||
void *ta_buf, uint32_t *pnum) | |||||
{ | |||||
struct mac_radix_cfg *cfg; | |||||
struct radix_node_head *rnh; | |||||
struct radix_node *rn; | |||||
struct ta_buf_radix *tb; | |||||
uint32_t *old_value, value; | |||||
cfg = (struct mac_radix_cfg *)ta_state; | |||||
tb = (struct ta_buf_radix *)ta_buf; | |||||
/* Save current entry value from @tei */ | |||||
rnh = ti->state; | |||||
((struct mac_radix_entry *)tb->ent_ptr)->value = tei->value; | |||||
/* Search for an entry first */ | |||||
rn = rnh->rnh_lookup(tb->addr_ptr, tb->mask_ptr, &rnh->rh); | |||||
if (rn != NULL) { | |||||
if ((tei->flags & TEI_FLAGS_UPDATE) == 0) | |||||
return (EEXIST); | |||||
/* Record already exists. Update value if we're asked to */ | |||||
old_value = &((struct mac_radix_entry *)rn)->value; | |||||
value = *old_value; | |||||
*old_value = tei->value; | |||||
tei->value = value; | |||||
/* Indicate that update has happened instead of addition */ | |||||
tei->flags |= TEI_FLAGS_UPDATED; | |||||
*pnum = 0; | |||||
return (0); | |||||
} | |||||
if ((tei->flags & TEI_FLAGS_DONTADD) != 0) | |||||
return (EFBIG); | |||||
rn = rnh->rnh_addaddr(tb->addr_ptr, tb->mask_ptr, &rnh->rh, tb->ent_ptr); | |||||
if (rn == NULL) { | |||||
/* Unknown error */ | |||||
return (EINVAL); | |||||
} | |||||
cfg->count++; | |||||
tb->ent_ptr = NULL; | |||||
*pnum = 1; | |||||
return (0); | |||||
} | |||||
static int | |||||
ta_prepare_del_mac_radix(struct ip_fw_chain *ch, struct tentry_info *tei, | |||||
void *ta_buf) | |||||
{ | |||||
struct ta_buf_radix *tb; | |||||
struct sockaddr *addr, *mask; | |||||
int mlen, set_mask; | |||||
tb = (struct ta_buf_radix *)ta_buf; | |||||
mlen = tei->masklen; | |||||
set_mask = 0; | |||||
if (tei->subtype == AF_LINK) { | |||||
if (mlen > 8 * ETHER_ADDR_LEN) | |||||
return (EINVAL); | |||||
addr = (struct sockaddr *)&tb->addr.mac.sa; | |||||
mask = (struct sockaddr *)&tb->addr.mac.ma; | |||||
} else | |||||
return (EINVAL); | |||||
tei_to_sockaddr_ent_mac(tei, addr, mask, &set_mask); | |||||
tb->addr_ptr = addr; | |||||
if (set_mask != 0) | |||||
tb->mask_ptr = mask; | |||||
return (0); | |||||
} | |||||
static int | |||||
ta_del_mac_radix(void *ta_state, struct table_info *ti, struct tentry_info *tei, | |||||
void *ta_buf, uint32_t *pnum) | |||||
{ | |||||
struct mac_radix_cfg *cfg; | |||||
struct radix_node_head *rnh; | |||||
struct radix_node *rn; | |||||
struct ta_buf_radix *tb; | |||||
cfg = (struct mac_radix_cfg *)ta_state; | |||||
tb = (struct ta_buf_radix *)ta_buf; | |||||
rnh = ti->state; | |||||
rn = rnh->rnh_deladdr(tb->addr_ptr, tb->mask_ptr, &rnh->rh); | |||||
if (rn == NULL) | |||||
return (ENOENT); | |||||
/* Save entry value to @tei */ | |||||
tei->value = ((struct mac_radix_entry *)rn)->value; | |||||
tb->ent_ptr = rn; | |||||
cfg->count--; | |||||
*pnum = 1; | |||||
return (0); | |||||
} | |||||
static void | |||||
ta_foreach_mac_radix(void *ta_state, struct table_info *ti, ta_foreach_f *f, | |||||
void *arg) | |||||
{ | |||||
struct radix_node_head *rnh; | |||||
rnh = (struct radix_node_head *)(ti->state); | |||||
rnh->rnh_walktree(&rnh->rh, (walktree_f_t *)f, arg); | |||||
} | |||||
static void | |||||
ta_dump_mac_radix_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo) | |||||
{ | |||||
struct mac_radix_cfg *cfg; | |||||
cfg = (struct mac_radix_cfg *)ta_state; | |||||
tinfo->flags = IPFW_TATFLAGS_AFDATA | IPFW_TATFLAGS_AFITEM; | |||||
tinfo->taclass4 = IPFW_TACLASS_RADIX; | |||||
tinfo->count4 = cfg->count; | |||||
tinfo->itemsize4 = sizeof(struct mac_radix_entry); | |||||
} | |||||
static int | |||||
ta_dump_mac_radix_tentry(void *ta_state, struct table_info *ti, void *e, | |||||
ipfw_obj_tentry *tent) | |||||
{ | |||||
struct mac_radix_entry *n = (struct mac_radix_entry *)e; | |||||
memcpy(tent->k.mac, n->sa.mac_addr.octet, ETHER_ADDR_LEN); | |||||
tent->masklen = n->masklen; | |||||
tent->subtype = AF_LINK; | |||||
tent->v.kidx = n->value; | |||||
return (0); | |||||
} | |||||
static int | |||||
ta_find_mac_radix_tentry(void *ta_state, struct table_info *ti, | |||||
ipfw_obj_tentry *tent) | |||||
{ | |||||
struct radix_node_head *rnh; | |||||
void *e; | |||||
e = NULL; | |||||
if (tent->subtype == AF_LINK) { | |||||
struct sa_mac sa; | |||||
KEY_LEN(sa) = KEY_LEN_MAC; | |||||
memcpy(tent->k.mac, sa.mac_addr.octet, ETHER_ADDR_LEN); | |||||
rnh = (struct radix_node_head *)ti->state; | |||||
e = rnh->rnh_matchaddr(&sa, &rnh->rh); | |||||
} | |||||
if (e != NULL) { | |||||
ta_dump_mac_radix_tentry(ta_state, ti, e, tent); | |||||
return (0); | |||||
} | |||||
return (ENOENT); | |||||
} | |||||
struct table_algo mac_radix = { | |||||
.name = "mac:radix", | |||||
.type = IPFW_TABLE_MAC, | |||||
.flags = TA_FLAG_DEFAULT, | |||||
.ta_buf_size = sizeof(struct ta_buf_radix), | |||||
.init = ta_init_mac_radix, | |||||
.destroy = ta_destroy_mac_radix, | |||||
.prepare_add = ta_prepare_add_mac_radix, | |||||
.prepare_del = ta_prepare_del_mac_radix, | |||||
.add = ta_add_mac_radix, | |||||
.del = ta_del_mac_radix, | |||||
.flush_entry = ta_flush_radix_entry, | |||||
.foreach = ta_foreach_mac_radix, | |||||
.dump_tentry = ta_dump_mac_radix_tentry, | |||||
.find_tentry = ta_find_mac_radix_tentry, | |||||
.dump_tinfo = ta_dump_mac_radix_tinfo, | |||||
.need_modify = ta_need_modify_radix, | |||||
}; | |||||
void | void | ||||
ipfw_table_algo_init(struct ip_fw_chain *ch) | ipfw_table_algo_init(struct ip_fw_chain *ch) | ||||
{ | { | ||||
size_t sz; | size_t sz; | ||||
/* | /* | ||||
* Register all algorithms presented here. | * Register all algorithms presented here. | ||||
*/ | */ | ||||
sz = sizeof(struct table_algo); | sz = sizeof(struct table_algo); | ||||
ipfw_add_table_algo(ch, &addr_radix, sz, &addr_radix.idx); | ipfw_add_table_algo(ch, &addr_radix, sz, &addr_radix.idx); | ||||
ipfw_add_table_algo(ch, &addr_hash, sz, &addr_hash.idx); | ipfw_add_table_algo(ch, &addr_hash, sz, &addr_hash.idx); | ||||
ipfw_add_table_algo(ch, &iface_idx, sz, &iface_idx.idx); | ipfw_add_table_algo(ch, &iface_idx, sz, &iface_idx.idx); | ||||
ipfw_add_table_algo(ch, &number_array, sz, &number_array.idx); | ipfw_add_table_algo(ch, &number_array, sz, &number_array.idx); | ||||
ipfw_add_table_algo(ch, &flow_hash, sz, &flow_hash.idx); | ipfw_add_table_algo(ch, &flow_hash, sz, &flow_hash.idx); | ||||
ipfw_add_table_algo(ch, &addr_kfib, sz, &addr_kfib.idx); | ipfw_add_table_algo(ch, &addr_kfib, sz, &addr_kfib.idx); | ||||
ipfw_add_table_algo(ch, &mac_radix, sz, &mac_radix.idx); | |||||
} | } | ||||
void | void | ||||
ipfw_table_algo_destroy(struct ip_fw_chain *ch) | ipfw_table_algo_destroy(struct ip_fw_chain *ch) | ||||
{ | { | ||||
ipfw_del_table_algo(ch, addr_radix.idx); | ipfw_del_table_algo(ch, addr_radix.idx); | ||||
ipfw_del_table_algo(ch, addr_hash.idx); | ipfw_del_table_algo(ch, addr_hash.idx); | ||||
ipfw_del_table_algo(ch, iface_idx.idx); | ipfw_del_table_algo(ch, iface_idx.idx); | ||||
ipfw_del_table_algo(ch, number_array.idx); | ipfw_del_table_algo(ch, number_array.idx); | ||||
ipfw_del_table_algo(ch, flow_hash.idx); | ipfw_del_table_algo(ch, flow_hash.idx); | ||||
ipfw_del_table_algo(ch, addr_kfib.idx); | ipfw_del_table_algo(ch, addr_kfib.idx); | ||||
ipfw_del_table_algo(ch, mac_radix.idx); | |||||
} | } |
Worth naming the fields according to other SA-like structures (mac_len, mac_addr).
Also - I'd rather add an explicit spare field between len and addr, so we get 2-byte aligned address & 8 byte-total structure (for ethernet).
You can also store prefixlen in this field (as it's before the radix offset).