0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00
This commit is contained in:
Maria Matejka 2023-01-18 12:33:06 +01:00
commit 6bb992cb04
13 changed files with 90 additions and 11 deletions

View File

@ -219,7 +219,7 @@ install-docs:
# Cleanup # Cleanup
clean:: clean::
rm -f $(objdir)/sysdep/paths.h rm -f $(objdir)/sysdep/paths.h $(objdir)/nest/proto-build.c
rm -f $(addprefix $(exedir)/,bird birdc birdcl) rm -f $(addprefix $(exedir)/,bird birdc birdcl)
find $(objdir) -name "*.[od]" -exec rm -f '{}' '+' find $(objdir) -name "*.[od]" -exec rm -f '{}' '+'

View File

@ -1816,6 +1816,14 @@ Common route attributes are:
creation/removal. Zero is returned for routes with undefined outgoing creation/removal. Zero is returned for routes with undefined outgoing
interfaces. Read-only. interfaces. Read-only.
<tag><label id="rta-onlink"><m/bool/ onlink</tag>
Onlink flag means that the specified nexthop is accessible on the
interface regardless of IP prefixes configured on the interface.
The attribute can be used to configure such next hops by first setting
<cf/onlink = true/ and <cf/ifname/, and then setting <cf/gw/. Possible
use case for setting this flag is to automatically build overlay IP-IP
networks on linux.
<tag><label id="rta-weight"><m/int/ weight</tag> <tag><label id="rta-weight"><m/int/ weight</tag>
Multipath weight of route next hops. Valid values are 1-256. Reading Multipath weight of route next hops. Valid values are 1-256. Reading
returns the weight of the first next hop, setting it sets weights of all returns the weight of the first next hop, setting it sets weights of all

View File

@ -305,7 +305,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
IF, THEN, ELSE, CASE, IF, THEN, ELSE, CASE,
FOR, IN, DO, FOR, IN, DO,
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC, TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS, FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS, ONLINK,
PREFERENCE, PREFERENCE,
ROA_CHECK, ASN, SRC, DST, ROA_CHECK, ASN, SRC, DST,
IS_V4, IS_V6, IS_V4, IS_V6,
@ -795,6 +795,7 @@ static_attr:
| WEIGHT { $$ = f_new_static_attr(T_INT, SA_WEIGHT, 0); } | WEIGHT { $$ = f_new_static_attr(T_INT, SA_WEIGHT, 0); }
| PREFERENCE { $$ = f_new_static_attr(T_INT, SA_PREF, 0); } | PREFERENCE { $$ = f_new_static_attr(T_INT, SA_PREF, 0); }
| GW_MPLS { $$ = f_new_static_attr(T_INT, SA_GW_MPLS, 0); } | GW_MPLS { $$ = f_new_static_attr(T_INT, SA_GW_MPLS, 0); }
| ONLINK { $$ = f_new_static_attr(T_BOOL, SA_ONLINK, 0); }
; ;
term: term:

View File

@ -102,6 +102,7 @@ enum f_sa_code {
SA_WEIGHT, SA_WEIGHT,
SA_PREF, SA_PREF,
SA_GW_MPLS, SA_GW_MPLS,
SA_ONLINK,
} PACKED; } PACKED;
/* Static attribute definition (members of struct rta) */ /* Static attribute definition (members of struct rta) */

View File

@ -694,6 +694,7 @@
case SA_WEIGHT: RESULT(sa.f_type, i, rta->nh.weight + 1); break; case SA_WEIGHT: RESULT(sa.f_type, i, rta->nh.weight + 1); break;
case SA_PREF: RESULT(sa.f_type, i, rta->pref); break; case SA_PREF: RESULT(sa.f_type, i, rta->pref); break;
case SA_GW_MPLS: RESULT(sa.f_type, i, rta->nh.labels ? rta->nh.label[0] : MPLS_NULL); break; case SA_GW_MPLS: RESULT(sa.f_type, i, rta->nh.labels ? rta->nh.label[0] : MPLS_NULL); break;
case SA_ONLINK: RESULT(sa.f_type, i, rta->nh.flags & RNF_ONLINK ? 1 : 0); break;
default: default:
bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code); bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
@ -720,8 +721,8 @@
case SA_GW: case SA_GW:
{ {
ip_addr ip = v1.val.ip; ip_addr ip = v1.val.ip;
struct iface *ifa = ipa_is_link_local(ip) ? rta->nh.iface : NULL; struct iface *ifa = ipa_is_link_local(ip) || (rta->nh.flags & RNF_ONLINK) ? rta->nh.iface : NULL;
neighbor *n = neigh_find((*fs->rte)->src->proto, ip, ifa, 0); neighbor *n = neigh_find((*fs->rte)->src->proto, ip, ifa, (rta->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);
if (!n || (n->scope == SCOPE_HOST)) if (!n || (n->scope == SCOPE_HOST))
runtime( "Invalid gw address" ); runtime( "Invalid gw address" );
@ -801,6 +802,15 @@
rta->pref = v1.val.i; rta->pref = v1.val.i;
break; break;
case SA_ONLINK:
{
if (v1.val.i)
rta->nh.flags |= RNF_ONLINK;
else
rta->nh.flags &= ~RNF_ONLINK;
}
break;
default: default:
bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code); bug("Invalid static attribute access (%u/%u)", sa.f_type, sa.sa_code);
} }

View File

@ -113,13 +113,13 @@ mrt_buffer_flush(buffer *b)
} }
#define MRT_DEFINE_TYPE(S, T) \ #define MRT_DEFINE_TYPE(S, T) \
static inline void mrt_put_##S##_(buffer *b, T x) \ static inline void UNUSED mrt_put_##S##_(buffer *b, T x) \
{ \ { \
put_##S(b->pos, x); \ put_##S(b->pos, x); \
b->pos += sizeof(T); \ b->pos += sizeof(T); \
} \ } \
\ \
static inline void mrt_put_##S(buffer *b, T x) \ static inline void UNUSED mrt_put_##S(buffer *b, T x) \
{ \ { \
mrt_buffer_need(b, sizeof(T)); \ mrt_buffer_need(b, sizeof(T)); \
put_##S(b->pos, x); \ put_##S(b->pos, x); \

View File

@ -10,7 +10,7 @@ CF_HDR
CF_DECLS CF_DECLS
CF_KEYWORDS(KERNEL, TABLE) CF_KEYWORDS(KERNEL, TABLE, METRIC)
CF_GRAMMAR CF_GRAMMAR
@ -25,6 +25,14 @@ kern_sys_item:
THIS_KRT->sys.table_id = $3; THIS_KRT->sys.table_id = $3;
} }
| METRIC expr {
if ($2 && !krt_max_metric)
cf_error("Kernel route metric not supported");
if ($2 > krt_max_metric)
cf_error("Kernel table id must be in range 0-%u", krt_max_metric);
THIS_KRT->sys.metric = $2;
}
; ;
CF_CODE CF_CODE

View File

@ -47,6 +47,11 @@ const int rt_default_ecmp = 0;
* table_id is specified explicitly as sysctl scan argument, while in FreeBSD it * table_id is specified explicitly as sysctl scan argument, while in FreeBSD it
* is handled implicitly by changing default table using setfib() syscall. * is handled implicitly by changing default table using setfib() syscall.
* *
* OpenBSD allows to use route metric. The behavior is controlled by these macro
* KRT_USE_METRIC, which enables use of rtm_priority in route send/recevive.
* There is also KRT_DEFAULT_METRIC and KRT_MAX_METRIC for default and maximum
* metric values.
*
* KRT_SHARED_SOCKET - use shared kernel socked instead of one for each krt_proto * KRT_SHARED_SOCKET - use shared kernel socked instead of one for each krt_proto
* KRT_USE_SETFIB_SCAN - use setfib() for sysctl() route scan * KRT_USE_SETFIB_SCAN - use setfib() for sysctl() route scan
* KRT_USE_SETFIB_SOCK - use SO_SETFIB socket option for kernel sockets * KRT_USE_SETFIB_SOCK - use SO_SETFIB socket option for kernel sockets
@ -63,6 +68,9 @@ const int rt_default_ecmp = 0;
#ifdef __OpenBSD__ #ifdef __OpenBSD__
#define KRT_MAX_TABLES (RT_TABLEID_MAX+1) #define KRT_MAX_TABLES (RT_TABLEID_MAX+1)
#define KRT_USE_METRIC
#define KRT_MAX_METRIC 255
#define KRT_DEFAULT_METRIC 56
#define KRT_SHARED_SOCKET #define KRT_SHARED_SOCKET
#define KRT_USE_SYSCTL_7 #define KRT_USE_SYSCTL_7
#endif #endif
@ -71,6 +79,14 @@ const int rt_default_ecmp = 0;
#define KRT_MAX_TABLES 1 #define KRT_MAX_TABLES 1
#endif #endif
#ifndef KRT_MAX_METRIC
#define KRT_MAX_METRIC 0
#endif
#ifndef KRT_DEFAULT_METRIC
#define KRT_DEFAULT_METRIC 0
#endif
/* Dynamic max number of tables */ /* Dynamic max number of tables */
@ -143,6 +159,10 @@ static struct krt_proto *krt_table_map[KRT_MAX_TABLES][2];
#endif #endif
/* Make it available to parser code */
const uint krt_max_metric = KRT_MAX_METRIC;
/* Route socket message processing */ /* Route socket message processing */
int int
@ -186,7 +206,7 @@ struct ks_msg
memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\ memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\
body += l;} body += l;}
static inline void static inline void UNUSED
sockaddr_fill_dl(struct sockaddr_dl *sa, struct iface *ifa) sockaddr_fill_dl(struct sockaddr_dl *sa, struct iface *ifa)
{ {
uint len = OFFSETOF(struct sockaddr_dl, sdl_data); uint len = OFFSETOF(struct sockaddr_dl, sdl_data);
@ -231,6 +251,10 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
msg.rtm.rtm_tableid = KRT_CF->sys.table_id; msg.rtm.rtm_tableid = KRT_CF->sys.table_id;
#endif #endif
#ifdef KRT_USE_METRIC
msg.rtm.rtm_priority = KRT_CF->sys.metric;
#endif
#ifdef RTF_REJECT #ifdef RTF_REJECT
if(a->dest == RTD_UNREACHABLE) if(a->dest == RTD_UNREACHABLE)
msg.rtm.rtm_flags |= RTF_REJECT; msg.rtm.rtm_flags |= RTF_REJECT;
@ -586,7 +610,7 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
e = rte_get_temp(&a, p->p.main_source); e = rte_get_temp(&a, p->p.main_source);
e->net = net; e->net = net;
ea_list *ea = alloca(sizeof(ea_list) + 1 * sizeof(eattr)); ea_list *ea = alloca(sizeof(ea_list) + 2 * sizeof(eattr));
*ea = (ea_list) { .count = 1, .next = e->attrs->eattrs }; *ea = (ea_list) { .count = 1, .next = e->attrs->eattrs };
e->attrs->eattrs = ea; e->attrs->eattrs = ea;
@ -596,6 +620,15 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
.u.data = src2, .u.data = src2,
}; };
#ifdef KRT_USE_METRIC
ea->count++;
ea->attrs[1] = (eattr) {
.id = EA_KRT_METRIC,
.type = EAF_TYPE_INT,
.u.data = msg->rtm.rtm_priority,
};
#endif
if (scan) if (scan)
krt_got_route(p, e, src); krt_got_route(p, e, src);
else else
@ -1155,7 +1188,7 @@ krt_sys_shutdown(struct krt_proto *p)
int int
krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o) krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
{ {
return n->sys.table_id == o->sys.table_id; return (n->sys.table_id == o->sys.table_id) && (n->sys.metric == o->sys.metric);
} }
void void
@ -1168,11 +1201,13 @@ krt_sys_preconfig(struct config *c UNUSED)
void krt_sys_init_config(struct krt_config *c) void krt_sys_init_config(struct krt_config *c)
{ {
c->sys.table_id = 0; /* Default table */ c->sys.table_id = 0; /* Default table */
c->sys.metric = KRT_DEFAULT_METRIC;
} }
void krt_sys_copy_config(struct krt_config *d, struct krt_config *s) void krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
{ {
d->sys.table_id = s->sys.table_id; d->sys.table_id = s->sys.table_id;
d->sys.metric = s->sys.metric;
} }

View File

@ -32,9 +32,11 @@ static inline void kif_sys_copy_config(struct kif_config *d UNUSED, struct kif_c
/* Kernel routes */ /* Kernel routes */
extern uint krt_max_tables; extern uint krt_max_tables;
extern const uint krt_max_metric;
struct krt_params { struct krt_params {
int table_id; /* Kernel table ID we sync with */ int table_id; /* Kernel table ID we sync with */
u32 metric; /* Kernel metric used for all routes */
}; };
struct krt_state { struct krt_state {

View File

@ -14,3 +14,6 @@ CONFIG_DONTROUTE_UNICAST Use MSG_DONTROUTE flag for unicast packets (def for Fre
CONFIG_USE_HDRINCL Use IP_HDRINCL instead of control messages for source address on raw IP sockets. CONFIG_USE_HDRINCL Use IP_HDRINCL instead of control messages for source address on raw IP sockets.
CONFIG_RESTRICTED_PRIVILEGES Implements restricted privileges using drop_uid() CONFIG_RESTRICTED_PRIVILEGES Implements restricted privileges using drop_uid()
CONFIG_MADV_DONTNEED_TO_FREE To free pages, use MADV_DONTNEED instead of MADV_FREE (linux)
CONFIG_DISABLE_THP Disable transparent huge pages (linux)

View File

@ -24,6 +24,7 @@
#define CONFIG_INCLUDE_SYSPRIV_H "sysdep/linux/syspriv.h" #define CONFIG_INCLUDE_SYSPRIV_H "sysdep/linux/syspriv.h"
#define CONFIG_MADV_DONTNEED_TO_FREE #define CONFIG_MADV_DONTNEED_TO_FREE
#define CONFIG_DISABLE_THP
#ifndef AF_MPLS #ifndef AF_MPLS
#define AF_MPLS 28 #define AF_MPLS 28

View File

@ -19,6 +19,10 @@
#include <sys/mman.h> #include <sys/mman.h>
#endif #endif
#ifdef CONFIG_DISABLE_THP
#include <sys/prctl.h>
#endif
long page_size = 0; long page_size = 0;
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
@ -222,6 +226,12 @@ global_free_pages_cleanup_event(void *data UNUSED)
void void
resource_sys_init(void) resource_sys_init(void)
{ {
#ifdef CONFIG_DISABLE_THP
/* Disable transparent huge pages, they do not work properly with madvice(MADV_DONTNEED) */
if (prctl(PR_SET_THP_DISABLE, (unsigned long) 1, (unsigned long) 0, (unsigned long) 0, (unsigned long) 0) < 0)
die("prctl(PR_SET_THP_DISABLE) failed: %m");
#endif
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
ASSERT_DIE(global_free_pages.cnt == 0); ASSERT_DIE(global_free_pages.cnt == 0);