mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
Filter: Add support for setting TCP congestion control algorithm
Allow to set TCP congestion control algorithm using krt_congctl route attribute. Based on patch from Trisha Biswas <tbiswas@fastly.com>, thanks!
This commit is contained in:
parent
224a152c53
commit
225943eaea
@ -3962,15 +3962,15 @@ these attributes:
|
|||||||
<p>In Linux, there is also a plenty of obscure route attributes mostly focused
|
<p>In Linux, there is also a plenty of obscure route attributes mostly focused
|
||||||
on tuning TCP performance of local connections. BIRD supports most of these
|
on tuning TCP performance of local connections. BIRD supports most of these
|
||||||
attributes, see Linux or iproute2 documentation for their meaning. Attributes
|
attributes, see Linux or iproute2 documentation for their meaning. Attributes
|
||||||
<cf/krt_lock_*/ and <cf/krt_feature_*/ have type bool, others have type int.
|
<cf/krt_lock_*/ and <cf/krt_feature_*/ have type bool, <cf/krt_congctl/ has type
|
||||||
Supported attributes are:
|
string, others have type int. Supported attributes are:
|
||||||
|
|
||||||
<cf/krt_mtu/, <cf/krt_lock_mtu/, <cf/krt_window/, <cf/krt_lock_window/,
|
<cf/krt_mtu/, <cf/krt_lock_mtu/, <cf/krt_window/, <cf/krt_lock_window/,
|
||||||
<cf/krt_rtt/, <cf/krt_lock_rtt/, <cf/krt_rttvar/, <cf/krt_lock_rttvar/,
|
<cf/krt_rtt/, <cf/krt_lock_rtt/, <cf/krt_rttvar/, <cf/krt_lock_rttvar/,
|
||||||
<cf/krt_sstresh/, <cf/krt_lock_sstresh/, <cf/krt_cwnd/, <cf/krt_lock_cwnd/,
|
<cf/krt_sstresh/, <cf/krt_lock_sstresh/, <cf/krt_cwnd/, <cf/krt_lock_cwnd/,
|
||||||
<cf/krt_advmss/, <cf/krt_lock_advmss/, <cf/krt_reordering/, <cf/krt_lock_reordering/,
|
<cf/krt_advmss/, <cf/krt_lock_advmss/, <cf/krt_reordering/, <cf/krt_lock_reordering/,
|
||||||
<cf/krt_hoplimit/, <cf/krt_lock_hoplimit/, <cf/krt_rto_min/, <cf/krt_lock_rto_min/,
|
<cf/krt_hoplimit/, <cf/krt_lock_hoplimit/, <cf/krt_rto_min/, <cf/krt_lock_rto_min/,
|
||||||
<cf/krt_initcwnd/, <cf/krt_initrwnd/, <cf/krt_quickack/,
|
<cf/krt_initcwnd/, <cf/krt_initrwnd/, <cf/krt_quickack/, <cf/krt_congctl/,
|
||||||
<cf/krt_feature_ecn/, <cf/krt_feature_allfrag/
|
<cf/krt_feature_ecn/, <cf/krt_feature_allfrag/
|
||||||
|
|
||||||
<sect1>Example
|
<sect1>Example
|
||||||
|
@ -39,7 +39,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i UNUSED) { return N
|
|||||||
#define EA_KRT_SCOPE EA_CODE(PROTOCOL_KERNEL, 0x12)
|
#define EA_KRT_SCOPE EA_CODE(PROTOCOL_KERNEL, 0x12)
|
||||||
|
|
||||||
|
|
||||||
#define KRT_METRICS_MAX 0x10 /* RTAX_QUICKACK+1 */
|
#define KRT_METRICS_MAX 0x11 /* RTAX_CC_ALGO+1 */
|
||||||
#define KRT_METRICS_OFFSET 0x20 /* Offset of EA_KRT_* vs RTAX_* */
|
#define KRT_METRICS_OFFSET 0x20 /* Offset of EA_KRT_* vs RTAX_* */
|
||||||
|
|
||||||
#define KRT_FEATURES_MAX 4
|
#define KRT_FEATURES_MAX 4
|
||||||
@ -64,6 +64,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i UNUSED) { return N
|
|||||||
#define EA_KRT_RTO_MIN EA_CODE(PROTOCOL_KERNEL, 0x2d)
|
#define EA_KRT_RTO_MIN EA_CODE(PROTOCOL_KERNEL, 0x2d)
|
||||||
#define EA_KRT_INITRWND EA_CODE(PROTOCOL_KERNEL, 0x2e)
|
#define EA_KRT_INITRWND EA_CODE(PROTOCOL_KERNEL, 0x2e)
|
||||||
#define EA_KRT_QUICKACK EA_CODE(PROTOCOL_KERNEL, 0x2f)
|
#define EA_KRT_QUICKACK EA_CODE(PROTOCOL_KERNEL, 0x2f)
|
||||||
|
#define EA_KRT_CONGCTL EA_CODE(PROTOCOL_KERNEL, 0x30)
|
||||||
|
|
||||||
|
|
||||||
struct krt_params {
|
struct krt_params {
|
||||||
|
@ -14,7 +14,7 @@ CF_KEYWORDS(KERNEL, TABLE, METRIC, NETLINK, RX, BUFFER,
|
|||||||
KRT_PREFSRC, KRT_REALM, KRT_SCOPE, KRT_MTU, KRT_WINDOW,
|
KRT_PREFSRC, KRT_REALM, KRT_SCOPE, KRT_MTU, KRT_WINDOW,
|
||||||
KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
|
KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
|
||||||
KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK,
|
KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK,
|
||||||
KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR,
|
KRT_CONGCTL, KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR,
|
||||||
KRT_LOCK_SSTRESH, KRT_LOCK_CWND, KRT_LOCK_ADVMSS, KRT_LOCK_REORDERING,
|
KRT_LOCK_SSTRESH, KRT_LOCK_CWND, KRT_LOCK_ADVMSS, KRT_LOCK_REORDERING,
|
||||||
KRT_LOCK_HOPLIMIT, KRT_LOCK_RTO_MIN, KRT_FEATURE_ECN, KRT_FEATURE_ALLFRAG)
|
KRT_LOCK_HOPLIMIT, KRT_LOCK_RTO_MIN, KRT_FEATURE_ECN, KRT_FEATURE_ALLFRAG)
|
||||||
|
|
||||||
@ -45,6 +45,7 @@ dynamic_attr: KRT_INITCWND { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT
|
|||||||
dynamic_attr: KRT_RTO_MIN { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_RTO_MIN); } ;
|
dynamic_attr: KRT_RTO_MIN { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_RTO_MIN); } ;
|
||||||
dynamic_attr: KRT_INITRWND { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_INITRWND); } ;
|
dynamic_attr: KRT_INITRWND { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_INITRWND); } ;
|
||||||
dynamic_attr: KRT_QUICKACK { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_QUICKACK); } ;
|
dynamic_attr: KRT_QUICKACK { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_QUICKACK); } ;
|
||||||
|
dynamic_attr: KRT_CONGCTL { $$ = f_new_dynamic_attr(EAF_TYPE_STRING, T_STRING, EA_KRT_CONGCTL); } ;
|
||||||
|
|
||||||
/* Bits of EA_KRT_LOCK, based on RTAX_* constants */
|
/* Bits of EA_KRT_LOCK, based on RTAX_* constants */
|
||||||
|
|
||||||
|
@ -479,6 +479,9 @@ static inline u16 rta_get_u16(struct rtattr *a)
|
|||||||
static inline u32 rta_get_u32(struct rtattr *a)
|
static inline u32 rta_get_u32(struct rtattr *a)
|
||||||
{ return *(u32 *) RTA_DATA(a); }
|
{ return *(u32 *) RTA_DATA(a); }
|
||||||
|
|
||||||
|
static inline const char *rta_get_str(struct rtattr *a)
|
||||||
|
{ return RTA_DATA(a); }
|
||||||
|
|
||||||
static inline ip4_addr rta_get_ip4(struct rtattr *a)
|
static inline ip4_addr rta_get_ip4(struct rtattr *a)
|
||||||
{ return ip4_ntoh(*(ip4_addr *) RTA_DATA(a)); }
|
{ return ip4_ntoh(*(ip4_addr *) RTA_DATA(a)); }
|
||||||
|
|
||||||
@ -569,6 +572,12 @@ nl_add_attr_u32(struct nlmsghdr *h, uint bufsize, int code, u32 data)
|
|||||||
nl_add_attr(h, bufsize, code, &data, 4);
|
nl_add_attr(h, bufsize, code, &data, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
nl_add_attr_str(struct nlmsghdr *h, unsigned bufsize, int code, const char *str)
|
||||||
|
{
|
||||||
|
nl_add_attr(h, bufsize, code, str, strlen(str) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
nl_add_attr_ip4(struct nlmsghdr *h, uint bufsize, int code, ip4_addr ip4)
|
nl_add_attr_ip4(struct nlmsghdr *h, uint bufsize, int code, ip4_addr ip4)
|
||||||
{
|
{
|
||||||
@ -822,21 +831,26 @@ err:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC_ASSERT(EA_KRT_METRICS + RTAX_CC_ALGO == EA_KRT_CONGCTL);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nl_add_metrics(struct nlmsghdr *h, uint bufsize, u32 *metrics, int max)
|
nl_add_metrics(struct nlmsghdr *h, uint bufsize, u32 *metrics, const char *cc_algo, int max)
|
||||||
{
|
{
|
||||||
struct rtattr *a = nl_open_attr(h, bufsize, RTA_METRICS);
|
struct rtattr *a = nl_open_attr(h, bufsize, RTA_METRICS);
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
for (t = 1; t < max; t++)
|
for (t = 1; t < max; t++)
|
||||||
if (metrics[0] & (1 << t))
|
if (metrics[0] & (1 << t))
|
||||||
nl_add_attr_u32(h, bufsize, t, metrics[t]);
|
if (t == RTAX_CC_ALGO)
|
||||||
|
nl_add_attr_str(h, bufsize, t, cc_algo);
|
||||||
|
else
|
||||||
|
nl_add_attr_u32(h, bufsize, t, metrics[t]);
|
||||||
|
|
||||||
nl_close_attr(h, a);
|
nl_close_attr(h, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nl_parse_metrics(struct rtattr *hdr, u32 *metrics, int max)
|
nl_parse_metrics(struct rtattr *hdr, u32 *metrics, const char **cc_algo, int max)
|
||||||
{
|
{
|
||||||
struct rtattr *a = RTA_DATA(hdr);
|
struct rtattr *a = RTA_DATA(hdr);
|
||||||
int len = RTA_PAYLOAD(hdr);
|
int len = RTA_PAYLOAD(hdr);
|
||||||
@ -844,17 +858,31 @@ nl_parse_metrics(struct rtattr *hdr, u32 *metrics, int max)
|
|||||||
metrics[0] = 0;
|
metrics[0] = 0;
|
||||||
for (; RTA_OK(a, len); a = RTA_NEXT(a, len))
|
for (; RTA_OK(a, len); a = RTA_NEXT(a, len))
|
||||||
{
|
{
|
||||||
if (a->rta_type == RTA_UNSPEC)
|
if (a->rta_type == RTAX_UNSPEC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (a->rta_type >= max)
|
if (a->rta_type >= max)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (RTA_PAYLOAD(a) != 4)
|
if (a->rta_type == RTAX_CC_ALGO)
|
||||||
return -1;
|
{
|
||||||
|
*cc_algo = rta_get_str(a);
|
||||||
|
int slen = RTA_PAYLOAD(a);
|
||||||
|
|
||||||
metrics[0] |= 1 << a->rta_type;
|
if (!slen || ((*cc_algo)[slen - 1] != 0))
|
||||||
metrics[a->rta_type] = rta_get_u32(a);
|
return -1;
|
||||||
|
|
||||||
|
metrics[0] |= 1 << a->rta_type;
|
||||||
|
metrics[a->rta_type] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (RTA_PAYLOAD(a) != 4)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
metrics[0] |= 1 << a->rta_type;
|
||||||
|
metrics[a->rta_type] = rta_get_u32(a);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
@ -1382,6 +1410,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op)
|
|||||||
|
|
||||||
|
|
||||||
u32 metrics[KRT_METRICS_MAX];
|
u32 metrics[KRT_METRICS_MAX];
|
||||||
|
const char *cc_algo = NULL;
|
||||||
metrics[0] = 0;
|
metrics[0] = 0;
|
||||||
|
|
||||||
struct ea_walk_state ews = { .eattrs = eattrs };
|
struct ea_walk_state ews = { .eattrs = eattrs };
|
||||||
@ -1389,11 +1418,15 @@ nl_send_route(struct krt_proto *p, rte *e, int op)
|
|||||||
{
|
{
|
||||||
int id = ea->id - EA_KRT_METRICS;
|
int id = ea->id - EA_KRT_METRICS;
|
||||||
metrics[0] |= 1 << id;
|
metrics[0] |= 1 << id;
|
||||||
metrics[id] = ea->u.data;
|
|
||||||
|
if (id == RTAX_CC_ALGO)
|
||||||
|
cc_algo = ea->u.ptr->data;
|
||||||
|
else
|
||||||
|
metrics[id] = ea->u.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metrics[0])
|
if (metrics[0])
|
||||||
nl_add_metrics(&r->h, rsize, metrics, KRT_METRICS_MAX);
|
nl_add_metrics(&r->h, rsize, metrics, cc_algo, KRT_METRICS_MAX);
|
||||||
|
|
||||||
switch (a->dest)
|
switch (a->dest)
|
||||||
{
|
{
|
||||||
@ -1795,10 +1828,11 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
|||||||
if (a[RTA_METRICS])
|
if (a[RTA_METRICS])
|
||||||
{
|
{
|
||||||
u32 metrics[KRT_METRICS_MAX];
|
u32 metrics[KRT_METRICS_MAX];
|
||||||
|
const char *cc_algo = NULL;
|
||||||
ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + KRT_METRICS_MAX * sizeof(eattr));
|
ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + KRT_METRICS_MAX * sizeof(eattr));
|
||||||
int t, n = 0;
|
int t, n = 0;
|
||||||
|
|
||||||
if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0)
|
if (nl_parse_metrics(a[RTA_METRICS], metrics, &cc_algo, ARRAY_SIZE(metrics)) < 0)
|
||||||
{
|
{
|
||||||
log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr);
|
log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr);
|
||||||
return;
|
return;
|
||||||
@ -1806,12 +1840,25 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
|||||||
|
|
||||||
for (t = 1; t < KRT_METRICS_MAX; t++)
|
for (t = 1; t < KRT_METRICS_MAX; t++)
|
||||||
if (metrics[0] & (1 << t))
|
if (metrics[0] & (1 << t))
|
||||||
ea->attrs[n++] = (eattr) {
|
if (t == RTAX_CC_ALGO)
|
||||||
.id = EA_CODE(PROTOCOL_KERNEL, KRT_METRICS_OFFSET + t),
|
{
|
||||||
.flags = 0,
|
struct adata *ad = lp_alloc_adata(s->pool, strlen(cc_algo));
|
||||||
.type = EAF_TYPE_INT, /* FIXME: Some are EAF_TYPE_BITFIELD */
|
memcpy(ad->data, cc_algo, ad->length);
|
||||||
.u.data = metrics[t],
|
|
||||||
};
|
ea->attrs[n++] = (eattr) {
|
||||||
|
.id = EA_KRT_CONGCTL,
|
||||||
|
.type = EAF_TYPE_STRING,
|
||||||
|
.u.ptr = ad,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ea->attrs[n++] = (eattr) {
|
||||||
|
.id = EA_KRT_METRICS + t,
|
||||||
|
.type = EAF_TYPE_INT, /* FIXME: Some are EAF_TYPE_BITFIELD */
|
||||||
|
.u.data = metrics[t],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
@ -2094,7 +2141,8 @@ krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
|
|||||||
|
|
||||||
static const char *krt_metrics_names[KRT_METRICS_MAX] = {
|
static const char *krt_metrics_names[KRT_METRICS_MAX] = {
|
||||||
NULL, "lock", "mtu", "window", "rtt", "rttvar", "sstresh", "cwnd", "advmss",
|
NULL, "lock", "mtu", "window", "rtt", "rttvar", "sstresh", "cwnd", "advmss",
|
||||||
"reordering", "hoplimit", "initcwnd", "features", "rto_min", "initrwnd", "quickack"
|
"reordering", "hoplimit", "initcwnd", "features", "rto_min", "initrwnd", "quickack",
|
||||||
|
"congctl"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *krt_features_names[KRT_FEATURES_MAX] = {
|
static const char *krt_features_names[KRT_FEATURES_MAX] = {
|
||||||
|
Loading…
Reference in New Issue
Block a user