Commit 937e75d8 authored by Ondřej Zajíček's avatar Ondřej Zajíček

Add the Babel routing protocol (RFC 6126)

This patch implements the IPv6 subset of the Babel routing protocol.
Based on the patch from Toke Hoiland-Jorgensen, with some heavy
modifications and bugfixes.

Thanks to Toke Hoiland-Jorgensen for the original patch.
parent a7baa098
......@@ -206,6 +206,9 @@ fi
AC_SUBST(iproutedir)
all_protocols="$proto_bfd bgp ospf pipe $proto_radv rip static"
if test "$ip" = ipv6 ; then
all_protocols="$all_protocols babel"
fi
all_protocols=`echo $all_protocols | sed 's/ /,/g'`
if test "$with_protocols" = all ; then
......
......@@ -1380,6 +1380,102 @@ corresponding protocol sections.
<chapt>Protocols
<sect>Babel
<sect1>Introduction
<p>The Babel protocol (RFC6126) is a loop-avoiding distance-vector routing
protocol that is robust and efficient both in ordinary wired networks and in
wireless mesh networks. Babel is conceptually very simple in its operation and
"just works" in its default configuration, though some configuration is possible
and in some cases desirable.
<p>While the Babel protocol is dual stack (i.e., can carry both IPv4 and IPv6
routes over the same IPv6 transport), BIRD presently implements only the IPv6
subset of the protocol. No Babel extensions are implemented, but the BIRD
implementation can coexist with implementations using the extensions (and will
just ignore extension messages).
<p>The Babel protocol implementation in BIRD is currently in alpha stage.
<sect1>Configuration
<p>Babel supports no global configuration options apart from those common to all
other protocols, but supports the following per-interface configuration options:
<code>
protocol babel [<name>] {
interface <interface pattern> {
type <wired|wireless>;
rxcost <number>;
hello interval <number>;
update interval <number>;
port <number>;
tx class|dscp <number>;
tx priority <number>;
rx buffer <number>;
tx length <number>;
check link <switch>;
};
}
</code>
<descrip>
<tag>type wired|wireless </tag>
This option specifies the interface type: Wired or wireless. Wired
interfaces are considered more reliable, and so the default hello
interval is higher, and a neighbour is considered unreachable after only
a small number of "hello" packets are lost. On wireless interfaces,
hello packets are sent more often, and the ETX link quality estimation
technique is used to compute the metrics of routes discovered over this
interface. This technique will gradually degrade the metric of routes
when packets are lost rather than the more binary up/down mechanism of
wired type links. Default: <cf/wired/.
<tag>rxcost <m/num/</tag>
This specifies the RX cost of the interface. The route metrics will be
computed from this value with a mechanism determined by the interface
<cf/type/. Default: 96 for wired interfaces, 256 for wireless.
<tag>hello interval <m/num/</tag>
Interval at which periodic "hello" messages are sent on this interface,
in seconds. Default: 4 seconds.
<tag>update interval <m/num/</tag>
Interval at which periodic (full) updates are sent. Default: 4 times the
hello interval.
<tag>port <m/number/</tag>
This option selects an UDP port to operate on. The default is to operate
on port 6696 as specified in the Babel RFC.
<tag>tx class|dscp|priority <m/number/</tag>
These options specify the ToS/DiffServ/Traffic class/Priority of the
outgoing Babel packets. See <ref id="dsc-prio" name="tx class"> common
option for detailed description.
<tag>rx buffer <m/number/</tag>
This option specifies the size of buffers used for packet processing.
The buffer size should be bigger than maximal size of received packets.
The default value is the interface MTU, and the value will be clamped to a
minimum of 512 bytes + IP packet overhead.
<tag>tx length <m/number/</tag>
This option specifies the maximum length of generated Babel packets. To
avoid IP fragmentation, it should not exceed the interface MTU value.
The default value is the interface MTU value, and the value will be
clamped to a minimum of 512 bytes + IP packet overhead.
<tag>check link <m/switch/</tag>
If set, the hardware link state (as reported by OS) is taken into
consideration. When the link disappears (e.g. an ethernet cable is
unplugged), neighbors are immediately considered unreachable and all
routes received from them are withdrawn. It is possible that some
hardware drivers or platforms do not implement this feature. Default:
yes.
</descrip>
<sect><label id="sect-bfd">BFD
<sect1>Introduction
......
......@@ -57,6 +57,9 @@ Reply codes of BIRD command-line interface
1020 Show BFD sessions
1021 Show RIP interface
1022 Show RIP neighbors
1023 Show Babel interfaces
1024 Show Babel neighbors
1025 Show Babel entries
8000 Reply too long
8001 Route not found
......
......@@ -60,6 +60,7 @@
#define NORET __attribute__((noreturn))
#define UNUSED __attribute__((unused))
#define PACKED __attribute__((packed))
/* Microsecond time */
......
......@@ -25,5 +25,6 @@ u32 u32_log2(u32 v);
static inline u32 u32_hash(u32 v) { return v * 2902958171u; }
#endif
static inline u8 u32_popcount(u32 v) { return __builtin_popcount(v); }
#endif
......@@ -26,6 +26,7 @@
#define IP6_OSPF_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 5)
#define IP6_OSPF_DES_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
#define IP6_RIP_ROUTERS ipa_build6(0xFF020000, 0, 0, 9)
#define IP6_BABEL_ROUTERS ipa_build6(0xFF020000, 0, 0, 0x00010006)
#define IP4_NONE _MI4(0)
#define IP6_NONE _MI6(0,0,0,0)
......
......@@ -124,6 +124,7 @@ static char * number(char * str, long num, int base, int size, int precision,
* width is automatically replaced by standard IP address width which
* depends on whether we use IPv4 or IPv6; |%#I| gives hexadecimal format),
* |%R| for Router / Network ID (u32 value printed as IPv4 address)
* |%lR| for 64bit Router / Network ID (u64 value printed as eight :-separated octets)
* and |%m| resp. |%M| for error messages (uses strerror() to translate @errno code to
* message text). On the other hand, it doesn't support floating
* point numbers.
......@@ -137,9 +138,10 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
unsigned long num;
int i, base;
u32 x;
u64 X;
char *str, *start;
const char *s;
char ipbuf[STD_ADDRESS_P_LENGTH+1];
char ipbuf[MAX(STD_ADDRESS_P_LENGTH,ROUTER_ID_64_LENGTH)+1];
struct iface *iface;
int flags; /* flags to number() */
......@@ -309,12 +311,27 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
/* Router/Network ID - essentially IPv4 address in u32 value */
case 'R':
if(qualifier == 'l') {
X = va_arg(args, u64);
bsprintf(ipbuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
((X >> 56) & 0xff),
((X >> 48) & 0xff),
((X >> 40) & 0xff),
((X >> 32) & 0xff),
((X >> 24) & 0xff),
((X >> 16) & 0xff),
((X >> 8) & 0xff),
(X & 0xff));
}
else
{
x = va_arg(args, u32);
bsprintf(ipbuf, "%d.%d.%d.%d",
((x >> 24) & 0xff),
((x >> 16) & 0xff),
((x >> 8) & 0xff),
(x & 0xff));
}
s = ipbuf;
goto str;
......
......@@ -30,4 +30,6 @@ static inline char *xbasename(const char *str)
return s ? s+1 : (char *) str;
}
#define ROUTER_ID_64_LENGTH 23
#endif
......@@ -919,6 +919,9 @@ protos_build(void)
proto_build(&proto_bfd);
bfd_init_all();
#endif
#ifdef CONFIG_BABEL
proto_build(&proto_babel);
#endif
proto_pool = rp_new(&root_pool, "Protocols");
proto_flush_event = ev_new(proto_pool);
......
......@@ -76,7 +76,7 @@ void protos_dump_all(void);
extern struct protocol
proto_device, proto_radv, proto_rip, proto_static,
proto_ospf, proto_pipe, proto_bgp, proto_bfd;
proto_ospf, proto_pipe, proto_bgp, proto_bfd, proto_babel;
/*
* Routing Protocol Instance
......
......@@ -219,6 +219,12 @@ typedef struct rte {
struct {
u8 suppressed; /* Used for deterministic MED comparison */
} bgp;
#endif
#ifdef CONFIG_BABEL
struct {
u16 metric; /* Babel metric */
u64 router_id; /* Babel router id */
} babel;
#endif
struct { /* Routes generated by krt sync (both temporary and inherited ones) */
s8 src; /* Alleged route source (see krt.h) */
......@@ -374,6 +380,7 @@ typedef struct rta {
#define RTS_OSPF_EXT2 10 /* OSPF external route type 2 */
#define RTS_BGP 11 /* BGP route */
#define RTS_PIPE 12 /* Inter-table wormhole */
#define RTS_BABEL 13 /* Babel route */
#define RTC_UNICAST 0
#define RTC_BROADCAST 1
......@@ -422,7 +429,8 @@ typedef struct eattr {
#define EAP_RIP 2 /* RIP */
#define EAP_OSPF 3 /* OSPF */
#define EAP_KRT 4 /* Kernel route attributes */
#define EAP_MAX 5
#define EAP_BABEL 5 /* Babel attributes */
#define EAP_MAX 6
#define EA_CODE(proto,id) (((proto) << 8) | (id))
#define EA_PROTO(ea) ((ea) >> 8)
......@@ -547,6 +555,7 @@ extern struct protocol *attr_class_to_protocol[EAP_MAX];
#define DEF_PREF_DIRECT 240 /* Directly connected */
#define DEF_PREF_STATIC 200 /* Static route */
#define DEF_PREF_OSPF 150 /* OSPF intra-area, inter-area and type 1 external routes */
#define DEF_PREF_BABEL 130 /* Babel */
#define DEF_PREF_RIP 120 /* RIP */
#define DEF_PREF_BGP 100 /* BGP */
#define DEF_PREF_PIPE 70 /* Routes piped from other tables */
......
H Protocols
C babel
C bfd
C bgp
C ospf
......
S babel.c
S packet.c
source=babel.c packets.c
root-rel=../../
dir-name=proto/babel
include ../../Rules
This diff is collapsed.
/*
* BIRD -- The Babel protocol
*
* Copyright (c) 2015--2016 Toke Hoiland-Jorgensen
*
* Can be freely distributed and used under the terms of the GNU GPL.
*
* This file contains the data structures used by Babel.
*/
#ifndef _BIRD_BABEL_H_
#define _BIRD_BABEL_H_
#include "nest/bird.h"
#include "nest/cli.h"
#include "nest/iface.h"
#include "nest/route.h"
#include "nest/protocol.h"
#include "nest/locks.h"
#include "lib/resource.h"
#include "lib/lists.h"
#include "lib/socket.h"
#include "lib/string.h"
#include "lib/timer.h"
#ifndef IPV6
#error "The Babel protocol only speaks IPv6"
#endif
#define EA_BABEL_METRIC EA_CODE(EAP_BABEL, 0)
#define EA_BABEL_ROUTER_ID EA_CODE(EAP_BABEL, 1)
#define BABEL_MAGIC 42
#define BABEL_VERSION 2
#define BABEL_PORT 6696
#define BABEL_INFINITY 0xFFFF
#define BABEL_HELLO_INTERVAL_WIRED 4 /* Default hello intervals in seconds */
#define BABEL_HELLO_INTERVAL_WIRELESS 4
#define BABEL_UPDATE_INTERVAL_FACTOR 4
#define BABEL_IHU_INTERVAL_FACTOR 3
#define BABEL_IHU_EXPIRY_FACTOR(X) ((X)*3/2) /* 1.5 */
#define BABEL_HELLO_EXPIRY_FACTOR(X) ((X)*3/2) /* 1.5 */
#define BABEL_ROUTE_EXPIRY_FACTOR(X) ((X)*7/2) /* 3.5 */
#define BABEL_ROUTE_REFRESH_INTERVAL 2 /* Seconds before route expiry to send route request */
#define BABEL_HOLD_TIME 10 /* Expiry time for our own routes */
#define BABEL_RXCOST_WIRED 96
#define BABEL_RXCOST_WIRELESS 256
#define BABEL_INITIAL_HOP_COUNT 255
#define BABEL_MAX_SEND_INTERVAL 5
#define BABEL_TIME_UNITS 100 /* On-wire times are counted in centiseconds */
#define BABEL_SEQNO_REQUEST_EXPIRY 60
#define BABEL_GARBAGE_INTERVAL 300
#define BABEL_OVERHEAD (SIZE_OF_IP_HEADER+UDP_HEADER_LENGTH)
#define BABEL_MIN_MTU (512 + BABEL_OVERHEAD)
enum babel_tlv_type {
BABEL_TLV_PAD1 = 0,
BABEL_TLV_PADN = 1,
BABEL_TLV_ACK_REQ = 2,
BABEL_TLV_ACK = 3,
BABEL_TLV_HELLO = 4,
BABEL_TLV_IHU = 5,
BABEL_TLV_ROUTER_ID = 6,
BABEL_TLV_NEXT_HOP = 7,
BABEL_TLV_UPDATE = 8,
BABEL_TLV_ROUTE_REQUEST = 9,
BABEL_TLV_SEQNO_REQUEST = 10,
/* extensions - not implemented
BABEL_TLV_TS_PC = 11,
BABEL_TLV_HMAC = 12,
BABEL_TLV_SS_UPDATE = 13,
BABEL_TLV_SS_REQUEST = 14,
BABEL_TLV_SS_SEQNO_REQUEST = 15,
*/
BABEL_TLV_MAX
};
enum babel_iface_type {
/* In practice, UNDEF and WIRED give equivalent behaviour */
BABEL_IFACE_TYPE_UNDEF = 0,
BABEL_IFACE_TYPE_WIRED = 1,
BABEL_IFACE_TYPE_WIRELESS = 2,
BABEL_IFACE_TYPE_MAX
};
enum babel_ae_type {
BABEL_AE_WILDCARD = 0,
BABEL_AE_IP4 = 1,
BABEL_AE_IP6 = 2,
BABEL_AE_IP6_LL = 3,
BABEL_AE_MAX
};
struct babel_config {
struct proto_config c;
list iface_list; /* Patterns configured -- keep it first; see babel_reconfigure why */
};
struct babel_iface_config {
struct iface_patt i;
u16 rxcost;
u8 type;
u8 check_link;
int port;
u16 hello_interval;
u16 ihu_interval;
u16 update_interval;
u16 rx_buffer; /* RX buffer size, 0 for MTU */
u16 tx_length; /* TX packet length limit (including headers), 0 for MTU */
int tx_tos;
int tx_priority;
};
struct babel_proto {
struct proto p;
timer *timer;
struct fib rtable;
list interfaces; /* Interfaces we really know about (struct babel_iface) */
u64 router_id;
u16 update_seqno; /* To be increased on request */
u8 triggered; /* For triggering global updates */
slab *route_slab;
slab *source_slab;
slab *msg_slab;
slab *seqno_slab;
list seqno_cache; /* Seqno requests in the cache (struct babel_seqno_request) */
struct tbf log_pkt_tbf; /* TBF for packet messages */
};
struct babel_iface {
node n;
struct babel_proto *proto;
struct iface *iface;
struct babel_iface_config *cf;
u8 up;
pool *pool;
char *ifname;
sock *sk;
ip_addr addr;
int tx_length;
list neigh_list; /* List of neighbors seen on this iface (struct babel_neighbor) */
list msg_queue;
u16 hello_seqno; /* To be increased on each hello */
bird_clock_t next_hello;
bird_clock_t next_regular;
bird_clock_t next_triggered;
bird_clock_t want_triggered;
timer *timer;
event *send_event;
};
struct babel_neighbor {
node n;
struct babel_iface *ifa;
ip_addr addr;
u16 txcost;
u8 hello_cnt;
u16 hello_map;
u16 next_hello_seqno;
/* expiry timers */
bird_clock_t hello_expiry;
bird_clock_t ihu_expiry;
list routes; /* Routes this neighbour has sent us (struct babel_route) */
};
struct babel_source {
node n;
u64 router_id;
u16 seqno;
u16 metric;
bird_clock_t expires;
};
struct babel_route {
node n;
node neigh_route;
struct babel_entry *e;
struct babel_neighbor *neigh;
u16 seqno;
u16 advert_metric;
u16 metric;
u64 router_id;
ip_addr next_hop;
bird_clock_t refresh_time;
bird_clock_t expires;
u16 expiry_interval;
};
struct babel_entry {
struct fib_node n;
struct babel_proto *proto;
struct babel_route *selected_in;
struct babel_route *selected_out;
bird_clock_t updated;
list sources; /* Source entries for this prefix (struct babel_source). */
list routes; /* Routes for this prefix (struct babel_route) */
};
/* Stores forwarded seqno requests for duplicate suppression. */
struct babel_seqno_request {
node n;
ip_addr prefix;
u8 plen;
u64 router_id;
u16 seqno;
bird_clock_t updated;
};
/*
* Internal TLV messages
*/
struct babel_msg_ack_req {
u8 type;
u16 nonce;
u16 interval;
ip_addr sender;
};
struct babel_msg_ack {
u8 type;
u16 nonce;
};
struct babel_msg_hello {
u8 type;
u16 seqno;
u16 interval;
ip_addr sender;
};
struct babel_msg_ihu {
u8 type;
u8 ae;
u16 rxcost;
u16 interval;
ip_addr addr;
ip_addr sender;
};
struct babel_msg_update {
u8 type;
u8 ae;
u8 plen;
u16 interval;
u16 seqno;
u16 metric;
ip_addr prefix;
u64 router_id;
ip_addr next_hop;
ip_addr sender;
};
struct babel_msg_route_request {
u8 type;
u8 full;
u8 plen;
ip_addr prefix;
};
struct babel_msg_seqno_request {
u8 type;
u8 plen;
u16 seqno;
u8 hop_count;
u64 router_id;
ip_addr prefix;
ip_addr sender;
};
union babel_msg {
u8 type;
struct babel_msg_ack_req ack_req;
struct babel_msg_ack ack;
struct babel_msg_hello hello;
struct babel_msg_ihu ihu;
struct babel_msg_update update;
struct babel_msg_route_request route_request;
struct babel_msg_seqno_request seqno_request;
};
struct babel_msg_node {
node n;
union babel_msg msg;
};
/* babel.c */
void babel_handle_ack_req(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_ack(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_hello(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_ihu(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_router_id(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_update(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_route_request(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_seqno_request(union babel_msg *msg, struct babel_iface *ifa);
void babel_show_interfaces(struct proto *P, char *iff);
void babel_show_neighbors(struct proto *P, char *iff);
void babel_show_entries(struct proto *P);
/* packets.c */
void babel_enqueue(union babel_msg *msg, struct babel_iface *ifa);
void babel_send_unicast(union babel_msg *msg, struct babel_iface *ifa, ip_addr dest);
int babel_open_socket(struct babel_iface *ifa);
void babel_send_queue(void *arg);
#endif
/*
* BIRD -- Babel Configuration
*
* Copyright (c) 2015-2016 Toke Hoiland-Jorgensen
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
CF_HDR
#include "proto/babel/babel.h"
#include "nest/iface.h"
CF_DEFINES
#define BABEL_CFG ((struct babel_config *) this_proto)
#define BABEL_IFACE ((struct babel_iface_config *) this_ipatt)
CF_DECLS
CF_KEYWORDS(BABEL, METRIC, RXCOST, HELLO, UPDATE, INTERVAL, PORT, WIRED,
WIRELESS, RX, TX, BUFFER, LENGTH, CHECK, LINK, BABEL_METRIC)
CF_GRAMMAR
CF_ADDTO(proto, babel_proto)
babel_proto_start: proto_start BABEL
{
this_proto = proto_config_new(&proto_babel, $1);
init_list(&BABEL_CFG->iface_list);
};
babel_proto_item:
proto_item
| INTERFACE babel_iface
;
babel_proto_opts:
/* empty */
| babel_proto_opts babel_proto_item ';'
;
babel_proto:
babel_proto_start proto_name '{' babel_proto_opts '}';
babel_iface_start:
{
this_ipatt = cfg_allocz(sizeof(struct babel_iface_config));
add_tail(&BABEL_CFG->iface_list, NODE this_ipatt);
init_list(&this_ipatt->ipn_list);
BABEL_IFACE->port = BABEL_PORT;
BABEL_IFACE->type = BABEL_IFACE_TYPE_WIRED;
BABEL_IFACE->tx_tos = IP_PREC_INTERNET_CONTROL;
BABEL_IFACE->tx_priority = sk_priority_control;
BABEL_IFACE->check_link = 1;
};
babel_iface_finish:
{
if (BABEL_IFACE->type == BABEL_IFACE_TYPE_WIRELESS)
{
if (!BABEL_IFACE->hello_interval)
BABEL_IFACE->hello_interval = BABEL_HELLO_INTERVAL_WIRELESS;
if (!BABEL_IFACE->rxcost)
BABEL_IFACE->rxcost = BABEL_RXCOST_WIRELESS;
}
else
{
if (!BABEL_IFACE->hello_interval)
BABEL_IFACE->hello_interval = BABEL_HELLO_INTERVAL_WIRED;
if (!BABEL_IFACE->rxcost)
BABEL_IFACE->rxcost = BABEL_RXCOST_WIRED;
}
if (!BABEL_IFACE->update_interval)
BABEL_IFACE->update_interval = BABEL_IFACE->hello_interval*BABEL_UPDATE_INTERVAL_FACTOR;
BABEL_IFACE->ihu_interval = BABEL_IFACE->hello_interval*BABEL_IHU_INTERVAL_FACTOR;
};
babel_iface_item:
| PORT expr { BABEL_IFACE->port = $2; if (($2<1) || ($2>65535)) cf_error("Invalid port number"); }
| RXCOST expr { BABEL_IFACE->rxcost = $2; if (($2<1) || ($2>65535)) cf_error("Invalid rxcost"); }
| HELLO INTERVAL expr { BABEL_IFACE->hello_interval = $3; if (($3<1) || ($3>65535)) cf_error("Invalid hello interval"); }
| UPDATE INTERVAL expr { BABEL_IFACE->update_interval = $3; if (($3<1) || ($3>65535)) cf_error("Invalid hello interval"); }
| TYPE WIRED { BABEL_IFACE->type = BABEL_IFACE_TYPE_WIRED; }
| TYPE WIRELESS { BABEL_IFACE->type = BABEL_IFACE_TYPE_WIRELESS; }
| RX BUFFER expr { BABEL_IFACE->rx_buffer = $3; if (($3<256) || ($3>65535)) cf_error("RX buffer must be in range 256-65535"); }
| TX LENGTH expr { BABEL_IFACE->tx_length = $3; if (($3<256) || ($3>65535)) cf_error("TX length must be in range 256-65535"); }
| TX tos { BABEL_IFACE->tx_tos = $2; }
| TX PRIORITY expr { BABEL_IFACE->tx_priority = $3; }
| CHECK LINK bool { BABEL_IFACE->check_link = $3; }
;
babel_iface_opts:
/* empty */
| babel_iface_opts babel_iface_item ';'
;
babel_iface_opt_list:
/* empty */
| '{' babel_iface_opts '}'
;
babel_iface:
babel_iface_start iface_patt_list_nopx babel_iface_opt_list babel_iface_finish;
CF_ADDTO(dynamic_attr, BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_BABEL_METRIC); })
CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]);
CF_CLI(SHOW BABEL INTERFACES, optsym opttext, [<name>] [\"<interface>\"], [[Show information about Babel interfaces]])
{ babel_show_interfaces(proto_get_named($4, &proto_babel), $5); };
CF_CLI(SHOW BABEL NEIGHBORS, optsym opttext, [<name>] [\"<interface>\"], [[Show information about Babel neighbors]])
{ babel_show_neighbors(proto_get_named($4, &proto_babel), $5); };
CF_CLI(SHOW BABEL ENTRIES, optsym opttext, [<name>], [[Show information about Babel prefix entries]])
{ babel_show_entries(proto_get_named($4, &proto_babel)); };
CF_CODE
CF_END
This diff is collapsed.
......@@ -43,6 +43,7 @@
#undef CONFIG_BGP
#undef CONFIG_OSPF
#undef CONFIG_PIPE
#undef CONFIG_BABEL
/* We use multithreading */
#undef USE_PTHREADS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment