Skip to content

Commit 3de9d62

Browse files
committed
add support for server affinity.
which means that EAP sessions can be directed to the correct home server in more situations.
1 parent 5c2e80d commit 3de9d62

3 files changed

Lines changed: 84 additions & 4 deletions

File tree

src/include/realms.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ typedef struct home_server {
8282
fr_ipaddr_t ipaddr; //!< IP address of home server.
8383
uint16_t port;
8484

85+
uint32_t affinity; //!< for home server fail-over groups and EAP.
86+
8587
char const *type_str; //!< String representation of type.
8688
home_type_t type; //!< Auth, Acct, CoA etc.
8789

@@ -105,7 +107,7 @@ typedef struct home_server {
105107
uint32_t response_timeouts;
106108
uint32_t max_response_timeouts;
107109
uint32_t max_outstanding; //!< Maximum outstanding requests.
108-
uint32_t currently_outstanding;
110+
uint32_t currently_outstanding;
109111

110112
time_t last_packet_sent;
111113
time_t last_packet_recv;
@@ -184,6 +186,8 @@ typedef struct home_pool_t {
184186
time_t time_all_dead;
185187
time_t last_serviced;
186188

189+
home_server_t **affinity_group;
190+
187191
int num_home_servers;
188192
home_server_t *servers[1];
189193
} home_pool_t;

src/main/process.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2774,6 +2774,24 @@ static int process_proxy_reply(REQUEST *request, RADIUS_PACKET *reply)
27742774
return 0;
27752775
}
27762776

2777+
/*
2778+
* If we have affinity, then maybe update State. But
2779+
* only for Access-Request, and only if there's a State
2780+
* attribute in the reply.
2781+
*/
2782+
if (request->home_pool->affinity_group &&
2783+
(request->packet->code == PW_CODE_ACCESS_REQUEST) &&
2784+
((vp = fr_pair_find_by_num(request->reply->vps, PW_STATE, 0, TAG_ANY)) != NULL)) {
2785+
uint8_t *src;
2786+
2787+
src = talloc_array(vp, uint8_t, vp->vp_length + 1);
2788+
if (!src) return 0;
2789+
2790+
src[0] = request->home_server->affinity;
2791+
memcpy(&src[1], vp->vp_octets, vp->vp_length);
2792+
fr_pair_value_memsteal(vp, src);
2793+
}
2794+
27772795
return 1;
27782796
}
27792797

src/main/realms.c

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,8 @@ static CONF_PARSER home_server_config[] = {
532532
{ "username", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, ping_user_name), NULL },
533533
{ "password", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_NOT_EMPTY, home_server_t, ping_user_password), NULL },
534534

535+
{ "affinity", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, affinity), NULL},
536+
535537
#ifdef WITH_STATS
536538
{ "historic_average_window", FR_CONF_OFFSET(PW_TYPE_INTEGER, home_server_t, ema.window), NULL },
537539
#endif
@@ -634,6 +636,8 @@ void realm_home_server_sanitize(home_server_t *home, CONF_SECTION *cs)
634636
if (parent && strcmp(cf_section_name1(parent), "server") == 0) {
635637
home->parent_server = cf_section_name2(parent);
636638
}
639+
640+
FR_INTEGER_BOUND_CHECK("coa_mrt", home->affinity, <=, 255);
637641
}
638642

639643
/** Insert a new home server into the various internal lookup trees
@@ -1636,6 +1640,35 @@ static int server_pool_add(realm_config_t *rc,
16361640
}
16371641
}
16381642

1643+
if (home->affinity) {
1644+
if (home->virtual_server) {
1645+
ERROR("Home server %s is a virtual server, and cannot be used with 'affinity'", home->name);
1646+
goto error;
1647+
}
1648+
1649+
if (!pool->affinity_group) {
1650+
pool->affinity_group = talloc_zero_array(pool, home_server_t *, pool->num_home_servers);
1651+
if (!pool->affinity_group) {
1652+
ERROR("Out of memory");
1653+
goto error;
1654+
}
1655+
}
1656+
1657+
if (home->affinity >= (uint32_t) pool->num_home_servers) {
1658+
ERROR("Home server %s has invalid 'affinity' value %u. It must be less than %u",
1659+
home->name, home->affinity, home->affinity, pool->num_home_servers);
1660+
goto error;
1661+
}
1662+
1663+
if (pool->affinity_group[home->affinity]) {
1664+
ERROR("Home server %s has invalid 'affinity' value %u. That value is already used by home server %s",
1665+
home->name, home->affinity, pool->affinity_group[home->affinity]->name);
1666+
goto error;
1667+
}
1668+
1669+
pool->affinity_group[home->affinity] = home;
1670+
}
1671+
16391672
if (!home) {
16401673
ERROR("Failed to find home server %s", value);
16411674
goto error;
@@ -1645,8 +1678,13 @@ static int server_pool_add(realm_config_t *rc,
16451678
pool->servers[num_home_servers++] = home;
16461679
} /* loop over home_server's */
16471680

1648-
if (pool->fallback && do_print) {
1649-
cf_log_info(cs, "\tfallback = %s", pool->fallback->name);
1681+
if (pool->fallback) {
1682+
if (do_print) cf_log_info(cs, "\tfallback = %s", pool->fallback->name);
1683+
1684+
if (pool->affinity_group) {
1685+
ERROR("Cannot use home server pool 'fallback' when home server 'affinity' is set");
1686+
goto error;
1687+
}
16501688
}
16511689

16521690
if (!realm_pool_add(pool, cs)) goto error;
@@ -2770,7 +2808,7 @@ void home_server_update_request(home_server_t *home, REQUEST *request)
27702808
}
27712809

27722810
home_server_t *home_server_ldb(char const *realmname,
2773-
home_pool_t *pool, REQUEST *request)
2811+
home_pool_t *pool, REQUEST *request)
27742812
{
27752813
int start;
27762814
int count;
@@ -2779,6 +2817,26 @@ home_server_t *home_server_ldb(char const *realmname,
27792817
VALUE_PAIR *vp;
27802818
uint32_t hash;
27812819

2820+
/*
2821+
* Over-ride the pool configuration if the pool is marked up as having affinity, AND the packet has a State attribute.
2822+
*/
2823+
if (pool->affinity_group &&
2824+
(request->packet->code == PW_CODE_ACCESS_REQUEST) &&
2825+
((vp = fr_pair_find_by_num(request->packet->vps, PW_STATE, 0, TAG_ANY)) != NULL) &&
2826+
(vp->vp_length > 1) &&
2827+
(vp->vp_octets[0] < (uint32_t) pool->num_home_servers) &&
2828+
(pool->affinity_group[vp->vp_octets[0]] != NULL)) {
2829+
found = pool->affinity_group[vp->vp_octets[0]];
2830+
2831+
if (HOME_SERVER_IS_DEAD(found)) return NULL;
2832+
2833+
/*
2834+
* Get rid of the extra octet that we added on the outbound proxying.
2835+
*/
2836+
fr_pair_value_memcpy(vp, vp->vp_octets + 1, vp->vp_length - 1);
2837+
return found;
2838+
}
2839+
27822840
/*
27832841
* Determine how to pick choose the home server.
27842842
*/

0 commit comments

Comments
 (0)