Skip to content

Commit 21a72ee

Browse files
author
Gabor Dozsa
committed
Support service listeners with multiple addresses
Enhancement issue #1813 Signed-off-by: Gabor Dozsa <gabor,[email protected]>
1 parent 0210860 commit 21a72ee

File tree

10 files changed

+330
-29
lines changed

10 files changed

+330
-29
lines changed

python/skupper_router/management/skrouter.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,12 @@
11091109
"type": "string",
11101110
"create": true
11111111
},
1112+
"multiAddressStrategy": {
1113+
"description": "Connection target address selection strategy for multi-address listener. If not 'none', the 'address' field is ignored and multiple service addresses can be specified for the listener by creating 'listenerAddress' entities. The strategy value determines how new connections select a target address. The only supported value is 'priorityFailover' currently. Priority failover strategy always selects the address with the highest priority value from the current set of reachable addresses.",
1114+
"type": "string",
1115+
"default": "none",
1116+
"required": false
1117+
},
11121118
"siteId": {
11131119
"type": "string",
11141120
"required": false,
@@ -1235,6 +1241,29 @@
12351241
}
12361242
},
12371243

1244+
"listenerAddress" : {
1245+
"description": "Configure a service address for a multi-address 'tcpListener'. The corresponding 'tcpListener' must specify the strategy for selecting target addresses for new connections.",
1246+
"extends": "configurationEntity",
1247+
"operations": ["CREATE", "DELETE"],
1248+
"attributes": {
1249+
"address": {
1250+
"description":"Service address.",
1251+
"type": "string",
1252+
"create": true
1253+
},
1254+
"value": {
1255+
"description":"Address selection strategy-specific numeric value (priority, etc.).",
1256+
"type": "integer",
1257+
"create": true
1258+
},
1259+
"listenerRef": {
1260+
"description":"Name of the 'tcpListener' this address belongs to.",
1261+
"type": "string",
1262+
"create": true
1263+
}
1264+
}
1265+
},
1266+
12381267
"log": {
12391268
"description": "Configure logging for a particular module. You can use the `UPDATE` operation to change log settings while the router is running.",
12401269
"extends": "configurationEntity",

python/skupper_router_internal/dispatch.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ def __init__(self) -> None:
112112
self._prototype(self.qd_dispatch_configure_tcp_listener, c_void_p, [self.qd_dispatch_p, py_object])
113113
self._prototype(self.qd_dispatch_delete_tcp_listener, None, [self.qd_dispatch_p, c_void_p])
114114
self._prototype(self.qd_dispatch_update_tcp_listener, c_void_p, [self.qd_dispatch_p, py_object, c_void_p])
115+
self._prototype(self.qd_dispatch_configure_tcp_listener_address, c_void_p, [self.qd_dispatch_p, py_object, c_void_p])
116+
self._prototype(self.qd_dispatch_delete_tcp_listener_address, None, [self.qd_dispatch_p, c_void_p])
115117
self._prototype(self.qd_dispatch_configure_listener, c_void_p, [self.qd_dispatch_p, py_object])
116118
self._prototype(self.qd_connection_manager_delete_listener, None, [self.qd_dispatch_p, c_void_p])
117119

python/skupper_router_internal/management/agent.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,21 @@ def _delete(self):
470470
self._qd.qd_connection_manager_delete_listener(self._dispatch, self._implementations[0].key)
471471

472472

473+
class ListenerAddressEntity(EntityAdapter):
474+
def create(self):
475+
config_listener_address = self._qd.qd_dispatch_configure_listener_address(self._dispatch, self)
476+
return config_listener_address
477+
478+
def _identifier(self):
479+
return _host_port_name_identifier(self)
480+
481+
def __str__(self):
482+
return super(ListenerAddressEntity, self).__str__().replace("Entity(", "ListenerAddressEntity(")
483+
484+
def _delete(self):
485+
self._qd.qd_dispatch_delete_listener_address(self._dispatch, self._implementations[0].key)
486+
487+
473488
class ConnectorEntity(ConnectionBaseEntity):
474489
def __init__(self, agent, entity_type, attributes=None, validate=True):
475490
super(ConnectorEntity, self).__init__(agent, entity_type, attributes,

src/adaptors/adaptor_common.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ qd_error_t qd_load_adaptor_config(qdr_core_t *core, qd_adaptor_config_t *config,
9090
if (config->backlog <= 0 || config->backlog > SOMAXCONN)
9191
config->backlog = SOMAXCONN;
9292

93+
config->multi_address_strategy = qd_entity_opt_string(entity, "multiAddressStrategy", "none"); CHECK();
94+
if (!strcmp(config->multi_address_strategy, "none") && !strcmp(config->multi_address_strategy, "priorityFailover")) {
95+
qd_error(QD_ERROR_VALUE, "Listener multi-address strategy value is invalid");
96+
goto error;
97+
}
98+
9399
int hplen = strlen(config->host) + strlen(config->port) + 2;
94100
config->host_port = malloc(hplen);
95101
snprintf(config->host_port, hplen, "%s:%s", config->host, config->port);
@@ -115,6 +121,19 @@ qd_error_t qd_load_adaptor_config(qdr_core_t *core, qd_adaptor_config_t *config,
115121
return qd_error_code();
116122
}
117123

124+
qd_error_t qd_load_listener_address_config(qdr_core_t *core, qd_listener_address_config_t *config, qd_entity_t *entity)
125+
{
126+
qd_error_clear();
127+
config->address = qd_entity_get_string(entity, "address"); CHECK();
128+
config->value = qd_entity_get_long(entity, "value"); CHECK();
129+
config->listener_name = qd_entity_get_string(entity, "listenerRef"); CHECK();
130+
131+
return QD_ERROR_NONE;
132+
133+
error:
134+
return qd_error_code();
135+
}
136+
118137
size_t qd_raw_conn_get_address_buf(pn_raw_connection_t *pn_raw_conn, char *buf, size_t buflen)
119138
{
120139
assert(pn_raw_conn);

src/adaptors/adaptor_common.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,16 @@ typedef enum {
4141
QD_AGGREGATION_MULTIPART
4242
} qd_http_aggregation_t;
4343

44+
45+
4446
typedef struct qd_adaptor_config_t qd_adaptor_config_t;
4547

4648
struct qd_adaptor_config_t
4749
{
4850
char *name;
4951
char *host;
5052
char *port;
53+
char *multi_address_strategy;
5154
char *address;
5255
char *site_id;
5356
char *host_port;
@@ -62,9 +65,21 @@ struct qd_adaptor_config_t
6265

6366
ALLOC_DECLARE(qd_adaptor_config_t);
6467

68+
typedef struct qd_listener_address_config_t qd_listener_address_config_t;
69+
70+
// Address config for multi-address listeners
71+
struct qd_listener_address_config_t {
72+
char *address;
73+
int value;
74+
char *listener_name;
75+
};
76+
6577
qd_error_t qd_load_adaptor_config(qdr_core_t *core, qd_adaptor_config_t *config, qd_entity_t *entity);
6678
void qd_free_adaptor_config(qd_adaptor_config_t *config);
6779

80+
qd_error_t qd_load_listener_address_config(qdr_core_t *core, qd_listener_address_config_t *config, qd_entity_t *entity);
81+
82+
6883
/**
6984
* Get the raw connections remote address.
7085
* Caller must free() the result when done.

0 commit comments

Comments
 (0)