0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-15 07:38:43 +00:00
bird/sysdep/unix/krt.Y
Maria Jan Matejka f93315c417 Config: Make the parser and lexer reentrant.
This is part of the multithreading journey. The parser and lexer were
using loads of global variables and all of these are now packed into
struct cf_context and others.

Note that the config API has changed:

* cfg_alloc[zu]?(size) is now cf_alloc[zu]?(ctx, size)
* cf_error(msg, ...) is now cf_error(ctx, msg, ...)
* config_parse() and cli_parse() are now called differently
* there is a brand new CF_CTX section in *.Y files which participates
  in struct cf_context construction
2018-09-14 14:44:45 +02:00

174 lines
4.0 KiB
Plaintext

/*
* BIRD -- UNIX Kernel Syncer Configuration
*
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
CF_HDR
#include "sysdep/unix/krt.h"
CF_CTX
struct kif_config *kif_cf;
struct krt_config *krt_cf;
CF_DEFINES
#define THIS_KRT ((struct krt_config *) ctx->this_proto)
#define THIS_KIF ((struct kif_config *) ctx->this_proto)
#define KIF_IFACE ((struct kif_iface_config *) ctx->this_ipatt)
static void
kif_set_preferred(struct cf_context *ctx, ip_addr ip)
{
if (ipa_is_ip4(ip))
KIF_IFACE->pref_v4 = ip;
else if (!ipa_is_link_local(ip))
KIF_IFACE->pref_v6 = ip;
else
KIF_IFACE->pref_ll = ip;
}
static struct proto_config *
kif_init_config(struct cf_context *ctx, int class)
{
if (ctx->kif_cf)
cf_error(ctx, "Kernel device protocol already defined");
ctx->kif_cf = (struct kif_config *) proto_config_new(ctx, &proto_unix_iface, class);
ctx->kif_cf->scan_time = 60 S_;
init_list(&ctx->kif_cf->iface_list);
kif_sys_init_config(ctx->kif_cf);
return (struct proto_config *) ctx->kif_cf;
}
struct proto_config *
krt_init_config(struct cf_context *ctx, int class)
{
#ifndef CONFIG_MULTIPLE_TABLES
if (ctx->krt_cf)
cf_error(ctx, "Kernel protocol already defined");
#endif
ctx->krt_cf = (struct krt_config *) proto_config_new(ctx, &proto_unix_kernel, class);
ctx->krt_cf->scan_time = 60 S_;
krt_sys_init_config(ctx->krt_cf);
return (struct proto_config *) ctx->krt_cf;
}
#ifdef CONFIG_ALL_TABLES_AT_ONCE
void
krt_check_scan_time(struct cf_context *ctx, struct krt_config *cf)
{
if (ctx->krt_cf->scan_time != cf->scan_time)
cf_error(ctx, "All kernel syncers must use the same table scan interval");
}
#endif
CF_DECLS
CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, GRACEFUL, RESTART, KRT_SOURCE, KRT_METRIC, MERGE, PATHS)
CF_KEYWORDS(INTERFACE, PREFERRED)
%type <i> kern_mp_limit
CF_GRAMMAR
/* Kernel syncer protocol */
proto: kern_proto '}' ;
kern_proto_start: proto_start KERNEL {
ctx->this_proto = krt_init_config(ctx, $1);
}
;
kern_proto: kern_proto_start proto_name '{' ;
kern_proto: kern_proto kern_item ';' ;
kern_mp_limit:
/* empty */ { $$ = KRT_DEFAULT_ECMP_LIMIT; }
| LIMIT expr { $$ = $2; if (($2 <= 0) || ($2 > 255)) cf_error(ctx, "Merge paths limit must be in range 1-255"); }
;
kern_item:
proto_item
| proto_channel { ctx->this_proto->net_type = $1->net_type; }
| PERSIST bool { THIS_KRT->persist = $2; }
| SCAN TIME expr {
/* Scan time of 0 means scan on startup only */
THIS_KRT->scan_time = $3 S_;
}
| LEARN bool {
THIS_KRT->learn = $2;
#ifndef KRT_ALLOW_LEARN
if ($2)
cf_error(ctx, "Learning of kernel routes not supported on this platform");
#endif
}
| GRACEFUL RESTART bool { THIS_KRT->graceful_restart = $3; }
| MERGE PATHS bool kern_mp_limit {
THIS_KRT->merge_paths = $3 ? $4 : 0;
#ifndef KRT_ALLOW_MERGE_PATHS
if ($3)
cf_error(ctx, "Path merging not supported on this platform");
#endif
}
;
/* Kernel interface protocol */
proto: kif_proto '}' ;
kif_proto_start: proto_start DEVICE { ctx->this_proto = kif_init_config(ctx, $1); }
;
kif_proto: kif_proto_start proto_name '{' ;
kif_proto: kif_proto kif_item ';' ;
kif_item:
proto_item
| INTERFACE kif_iface
| SCAN TIME expr {
/* Scan time of 0 means scan on startup only */
THIS_KIF->scan_time = $3 S_;
}
;
kif_iface_start:
{
ctx->this_ipatt = cfg_allocz(sizeof(struct kif_iface_config));
add_tail(&THIS_KIF->iface_list, NODE ctx->this_ipatt);
init_list(&ctx->this_ipatt->ipn_list);
}
kif_iface_item:
PREFERRED ipa { kif_set_preferred(ctx, $2); }
;
kif_iface_opts:
/* empty */
| kif_iface_opts kif_iface_item ';'
;
kif_iface_opt_list:
/* empty */
| '{' kif_iface_opts '}'
;
kif_iface:
kif_iface_start iface_patt_list_nopx kif_iface_opt_list;
dynamic_attr: KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SOURCE); } ;
dynamic_attr: KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_METRIC); } ;
CF_CODE
CF_END