0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-03 07:31:54 +00:00

Merge branch 'maarten' into mq-ordered

This commit is contained in:
Jan Maria Matejka 2018-12-12 13:10:10 +01:00
commit c217fe593a
11 changed files with 218 additions and 45 deletions

View File

@ -1094,8 +1094,10 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
ADVANCE(pos, len, alen);
}
#define FAIL(KEY) ({ STATS(KEY); goto fail; })
if (s->err_withdraw)
goto withdraw;
FAIL(bad_attribute);
/* If there is no reachability NLRI, we are finished */
if (!s->ip_reach_len && !s->mp_reach_len)
@ -1104,10 +1106,10 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
/* Handle missing mandatory attributes; RFC 7606 3 (d) */
if (!BIT32_TEST(s->attrs_seen, BA_ORIGIN))
{ REPORT(NO_MANDATORY, "ORIGIN"); goto withdraw; }
{ REPORT(NO_MANDATORY, "ORIGIN"); FAIL(no_mandatory); }
if (!BIT32_TEST(s->attrs_seen, BA_AS_PATH))
{ REPORT(NO_MANDATORY, "AS_PATH"); goto withdraw; }
{ REPORT(NO_MANDATORY, "AS_PATH"); FAIL(no_mandatory); }
/* When receiving attributes from non-AS4-aware BGP speaker, we have to
reconstruct AS_PATH and AGGREGATOR attributes; RFC 6793 4.2.3 */
@ -1116,19 +1118,19 @@ bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len)
/* Reject routes with our ASN in AS_PATH attribute */
if (bgp_as_path_loopy(p, attrs, p->local_as))
goto withdraw;
FAIL(loopy);
/* Reject routes with our Confederation ID in AS_PATH attribute; RFC 5065 4.0 */
if ((p->public_as != p->local_as) && bgp_as_path_loopy(p, attrs, p->public_as))
goto withdraw;
FAIL(loopy);
/* Reject routes with our Router ID in ORIGINATOR_ID attribute; RFC 4456 8 */
if (p->is_internal && bgp_originator_id_loopy(p, attrs))
goto withdraw;
FAIL(loopy);
/* Reject routes with our Cluster ID in CLUSTER_LIST attribute; RFC 4456 8 */
if (p->rr_client && bgp_cluster_list_loopy(p, attrs))
goto withdraw;
FAIL(loopy);
/* If there is no local preference, define one */
if (!BIT32_TEST(s->attrs_seen, BA_LOCAL_PREF))
@ -1141,8 +1143,11 @@ framing_error:
/* RFC 7606 4 - handle attribute framing errors */
REPORT("Malformed attribute list - framing error (%u/%u) at %d",
alen, len, (int) (pos - s->attrs));
FAIL(bad_alist);
withdraw:
#undef FAIL
fail:
/* RFC 7606 5.2 - handle missing NLRI during errors */
if (!s->ip_reach_len && !s->mp_reach_len)
bgp_parse_error(s, 1);
@ -2009,11 +2014,13 @@ bgp_get_attr(eattr *a, byte *buf, int buflen)
void
bgp_get_route_info(rte *e, byte *buf, ea_list *attrs)
{
struct bgp_proto *bgp = (void *) e->attrs->src->proto;
eattr *p = ea_find(attrs, EA_CODE(EAP_BGP, BA_AS_PATH));
eattr *o = ea_find(attrs, EA_CODE(EAP_BGP, BA_ORIGIN));
u32 origas;
buf += bsprintf(buf, " (%d", e->pref);
char c = bgp->is_internal ? 'I' : (bgp->is_interior ? 'C' : 'E');
buf += bsprintf(buf, " %c (%d", c, e->pref);
if (e->u.bgp.suppressed)
buf += bsprintf(buf, "-");

View File

@ -1328,6 +1328,8 @@ bgp_start(struct proto *P)
p->source_addr = p->cf->local_ip;
p->link_addr = IPA_NONE;
memset(&(p->stats), 0, sizeof(struct bgp_stats));
/* Lock all channels when in GR recovery mode */
if (p->p.gr_recovery && p->cf->gr_mode)
{
@ -2104,6 +2106,15 @@ bgp_show_proto_info(struct proto *P)
tm_remains(p->conn->keepalive_timer), p->conn->keepalive_time);
}
struct bgp_stats *s = &p->stats;
cli_msg(-1006, " Statistics:");
cli_msg(-1006, " rx-open %u rx-update %u rx-notify %u rx-keepalive %u rx-refresh %u",
s->rx_pkts[0], s->rx_pkts[1], s->rx_pkts[2], s->rx_pkts[3], s->rx_pkts[4]);
cli_msg(-1006, " tx-open %u tx-update %u tx-notify %u tx-keepalive %u tx-refresh %u",
s->tx_pkts[0], s->tx_pkts[1], s->tx_pkts[2], s->tx_pkts[3], s->tx_pkts[4]);
cli_msg(-1006, " bad-alist %u bad-attribute %u bad-next-hop %u no-mandatory %u loopy %u",
s->bad_alist, s->bad_attribute, s->bad_next_hop, s->no_mandatory, s->loopy);
if ((p->last_error_class != BE_NONE) &&
(p->last_error_class != BE_MAN_DOWN))
{
@ -2120,6 +2131,9 @@ bgp_show_proto_info(struct proto *P)
if (c->c.channel_state == CS_UP)
{
cli_msg(-1006, " Enqueued updates: %u", c->bucket_hash.count);
cli_msg(-1006, " Enqueued prefixes: %u", c->prefix_hash.count);
if (ipa_zero(c->link_addr))
cli_msg(-1006, " BGP Next hop: %I", c->next_hop_addr);
else

View File

@ -55,6 +55,8 @@ struct eattr;
#define BGP_AF_FLOW4 BGP_AF( BGP_AFI_IPV4, BGP_SAFI_FLOW )
#define BGP_AF_FLOW6 BGP_AF( BGP_AFI_IPV6, BGP_SAFI_FLOW )
#define BGP_PKT_TYPES 5 /* PKT_OPEN .. PKT_ROUTE_REFRESH */
struct bgp_write_state;
struct bgp_parse_state;
@ -196,6 +198,14 @@ struct bgp_caps {
#define WALK_AF_CAPS(caps,ac) \
for (ac = caps->af_data; ac < &caps->af_data[caps->af_count]; ac++)
struct bgp_stats {
uint rx_pkts[BGP_PKT_TYPES], tx_pkts[BGP_PKT_TYPES];
uint bad_alist, bad_attribute, bad_next_hop, no_mandatory, loopy;
};
#ifndef PARSER
#define STATS(KEY) ({ p->stats.KEY++; })
#endif
struct bgp_socket {
node n; /* Node in global bgp_sockets */
@ -254,6 +264,7 @@ struct bgp_proto {
struct neighbor *neigh; /* Neighbor entry corresponding to remote ip, NULL if multihop */
struct bgp_socket *sock; /* Shared listening socket */
struct bfd_request *bfd_req; /* BFD request, if BFD is used */
struct bgp_stats stats; /* Packet statistics */
ip_addr source_addr; /* Local address used as an advertised next hop */
ip_addr link_addr; /* Link-local version of source_addr */
event *event; /* Event for respawning and shutting process */

View File

@ -2174,6 +2174,7 @@ bgp_rx_end_mark(struct bgp_parse_state *s, u32 afi)
static inline void
bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_list *ea, byte *nh, uint nh_len)
{
struct bgp_proto *p = s->proto;
struct bgp_channel *c = bgp_get_channel(s->proto, afi);
rta *a = NULL;
@ -2207,7 +2208,10 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
/* Handle withdraw during next hop decoding */
if (s->err_withdraw)
{
STATS(bad_next_hop);
a = NULL;
}
}
c->desc->decode_nlri(s, nlri, len, a);
@ -2446,6 +2450,7 @@ found:
static inline int
bgp_send(struct bgp_conn *conn, uint type, uint len)
{
struct bgp_proto *p = conn->bgp;
sock *sk = conn->sk;
byte *buf = sk->tbuf;
@ -2453,6 +2458,7 @@ bgp_send(struct bgp_conn *conn, uint type, uint len)
put_u16(buf+16, len);
buf[18] = type;
STATS(tx_pkts[type - 1]);
return sk_send(sk, len);
}
@ -2812,13 +2818,22 @@ bgp_rx_keepalive(struct bgp_conn *conn)
static void
bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
{
struct bgp_proto *p = conn->bgp;
byte type = pkt[18];
DBG("BGP: Got packet %02x (%d bytes)\n", type, len);
if (conn->bgp->p.mrtdump & MD_MESSAGES)
if (p->p.mrtdump & MD_MESSAGES)
mrt_dump_bgp_packet(conn, pkt, len);
if (type < PKT_OPEN || type > PKT_ROUTE_REFRESH)
{
bgp_error(conn, 1, 3, pkt+18, 1);
return;
}
STATS(rx_pkts[type - 1]);
switch (type)
{
case PKT_OPEN: return bgp_rx_open(conn, pkt, len);
@ -2826,7 +2841,6 @@ bgp_rx_packet(struct bgp_conn *conn, byte *pkt, uint len)
case PKT_NOTIFICATION: return bgp_rx_notification(conn, pkt, len);
case PKT_KEEPALIVE: return bgp_rx_keepalive(conn);
case PKT_ROUTE_REFRESH: return bgp_rx_route_refresh(conn, pkt, len);
default: bgp_error(conn, 1, 3, pkt+18, 1);
}
}

View File

@ -135,6 +135,8 @@ stat_route:
stat_route_item:
cmd { *this_srt_last_cmd = $1; this_srt_last_cmd = &($1->next); }
| PREFERENCE expr ';' { this_srt->preference = $2; check_u16($2); }
| DISTANCE expr ';' { this_srt->preference = $2; check_u16($2); }
;
stat_route_opts:

View File

@ -53,7 +53,7 @@ static void
static_announce_rte(struct static_proto *p, struct static_route *r)
{
rta *a = allocz(RTA_MAX_SIZE);
a->src = p->p.main_source;
a->src = rt_get_source(&p->p, r->preference);
a->source = RTS_STATIC;
a->scope = SCOPE_UNIVERSE;
a->dest = r->dest;
@ -101,11 +101,13 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
/* We skip rta_lookup() here */
rte *e = rte_get_temp(a);
e->pflags = 0;
e->pref = r->preference;
if (r->cmds)
f_eval_rte(r->cmds, &e, static_lp);
rte_update(&p->p, r->net, e);
e->pref = r->preference; /* Avoid preference from filter */
rte_update2(p->p.main_channel, r->net, e, a->src);
r->state = SRS_CLEAN;
if (r->cmds)
@ -117,7 +119,7 @@ withdraw:
if (r->state == SRS_DOWN)
return;
rte_update(&p->p, r->net, NULL);
rte_update2(p->p.main_channel, r->net, NULL, a->src);
r->state = SRS_DOWN;
}
@ -250,7 +252,7 @@ static void
static_remove_rte(struct static_proto *p, struct static_route *r)
{
if (r->state)
rte_update(&p->p, r->net, NULL);
rte_update2(p->p.main_channel, r->net, NULL, rt_get_source(&p->p, r->preference));
static_reset_rte(p, r);
}
@ -380,8 +382,13 @@ static_postconfig(struct proto_config *CF)
cc->table : cf->c.global->def_tables[NET_IP6];
WALK_LIST(r, cf->routes)
{
if (r->net && (r->net->type != CF->net_type))
cf_error("Route %N incompatible with channel type", r->net);
if (!r->preference)
r->preference = cc->preference;
}
}
static struct proto *
@ -488,11 +495,17 @@ static_dump(struct proto *P)
#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL )
static inline int srt_equal(struct static_route *a, struct static_route *b)
{ return net_equal(a->net, b->net) && (a->preference == b->preference); }
static inline int srt_compare(struct static_route *a, struct static_route *b)
{ return net_compare(a->net, b->net) ?: uint_cmp(a->preference, b->preference); }
static inline int
static_cmp_rte(const void *X, const void *Y)
{
struct static_route *x = *(void **)X, *y = *(void **)Y;
return net_compare(x->net, y->net);
return srt_compare(x, y);
}
static int
@ -521,7 +534,7 @@ static_reconfigure(struct proto *P, struct proto_config *CF)
/* Reconfigure initial matching sequence */
for (or = HEAD(o->routes), nr = HEAD(n->routes);
NODE_VALID(or) && NODE_VALID(nr) && net_equal(or->net, nr->net);
NODE_VALID(or) && NODE_VALID(nr) && srt_equal(or, nr);
or = NODE_NEXT(or), nr = NODE_NEXT(nr))
static_reconfigure_rte(p, or, nr);
@ -552,7 +565,7 @@ static_reconfigure(struct proto *P, struct proto_config *CF)
while ((orpos < ornum) && (nrpos < nrnum))
{
int x = net_compare(orbuf[orpos]->net, nrbuf[nrpos]->net);
int x = srt_compare(orbuf[orpos], nrbuf[nrpos]);
if (x < 0)
static_remove_rte(p, orbuf[orpos++]);
else if (x > 0)

View File

@ -40,6 +40,7 @@ struct static_route {
struct static_route *mp_head; /* First nexthop of this route */
struct static_route *mp_next; /* Nexthops for multipath routes */
struct f_inst *cmds; /* List of commands for setting attributes */
u16 preference; /* Route preference */
byte dest; /* Destination type (RTD_*) */
byte state; /* State of route announcement (SRS_*) */
byte active; /* Next hop is active (nbr/iface/BFD available) */

View File

@ -11,13 +11,16 @@ CF_HDR
#include "sysdep/unix/unix.h"
#include <stdio.h>
CF_DEFINES
static struct log_config *this_log;
CF_DECLS
CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
CF_KEYWORDS(NAME, CONFIRM, UNDO, CHECK, TIMEOUT, DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING)
%type <i> log_mask log_mask_list log_cat cfg_timeout
%type <g> log_file
%type <t> cfg_name
%type <tf> timeformat_which
%type <t> syslog_name
@ -26,11 +29,11 @@ CF_GRAMMAR
CF_ADDTO(conf, log_config)
log_config: LOG log_file log_mask ';' {
struct log_config *c = cfg_allocz(sizeof(struct log_config));
c->fh = $2;
c->mask = $3;
add_tail(&new_config->logfiles, &c->n);
log_begin: { this_log = cfg_allocz(sizeof(struct log_config)); };
log_config: LOG log_begin log_file log_mask ';' {
this_log->mask = $4;
add_tail(&new_config->logfiles, &this_log->n);
}
;
@ -39,14 +42,21 @@ syslog_name:
| { $$ = bird_name; }
;
log_limit:
/* empty */
| expr text { this_log->limit = $1; this_log->backup = $2; }
;
log_file:
text {
FILE *f = tracked_fopen(new_config->pool, $1, "a");
if (!f) cf_error("Unable to open log file `%s': %m", $1);
$$ = f;
text log_limit {
this_log->rf = rf_open(new_config->pool, $1, "a");
if (!this_log->rf) cf_error("Unable to open log file '%s': %m", $1);
this_log->fh = rf_file(this_log->rf);
this_log->pos = -1;
this_log->filename = $1;
}
| SYSLOG syslog_name { $$ = NULL; new_config->syslog_name = $2; }
| STDERR { $$ = stderr; }
| SYSLOG syslog_name { this_log->fh = NULL; new_config->syslog_name = $2; }
| STDERR { this_log->fh = stderr; }
;
log_mask:
@ -77,9 +87,9 @@ CF_ADDTO(conf, mrtdump_base)
mrtdump_base:
MRTDUMP PROTOCOLS mrtdump_mask ';' { new_config->proto_default_mrtdump = $3; }
| MRTDUMP text ';' {
FILE *f = tracked_fopen(new_config->pool, $2, "a");
struct rfile *f = rf_open(new_config->pool, $2, "a");
if (!f) cf_error("Unable to open MRTDump file '%s': %m", $2);
new_config->mrtdump_file = fileno(f);
new_config->mrtdump_file = rf_fileno(f);
}
;

View File

@ -55,6 +55,7 @@
this to gen small latencies */
#define MAX_RX_STEPS 4
/*
* Tracked Files
*/
@ -89,17 +90,29 @@ static struct resclass rf_class = {
NULL
};
void *
tracked_fopen(pool *p, char *name, char *mode)
struct rfile *
rf_open(pool *p, char *name, char *mode)
{
FILE *f = fopen(name, mode);
if (f)
{
struct rfile *r = ralloc(p, &rf_class);
r->f = f;
}
return f;
if (!f)
return NULL;
struct rfile *r = ralloc(p, &rf_class);
r->f = f;
return r;
}
void *
rf_file(struct rfile *f)
{
return f->f;
}
int
rf_fileno(struct rfile *f)
{
return fileno(f->f);
}

View File

@ -19,6 +19,8 @@
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
@ -86,6 +88,54 @@ static char *class_names[] = {
"BUG"
};
static inline off_t
log_size(struct log_config *l)
{
struct stat st;
return (!fstat(rf_fileno(l->rf), &st) && S_ISREG(st.st_mode)) ? st.st_size : 0;
}
static void
log_close(struct log_config *l)
{
rfree(l->rf);
l->rf = NULL;
l->fh = NULL;
}
static int
log_open(struct log_config *l)
{
l->rf = rf_open(config->pool, l->filename, "a");
if (!l->rf)
{
/* Well, we cannot do much in case of error as log is closed */
l->mask = 0;
return -1;
}
l->fh = rf_file(l->rf);
l->pos = log_size(l);
return 0;
}
static int
log_rotate(struct log_config *l)
{
log_close(l);
/* If we cannot rename the logfile, we at least try to delete it
in order to continue logging and not exceeding logfile size */
if ((rename(l->filename, l->backup) < 0) &&
(unlink(l->filename) < 0))
{
l->mask = 0;
return -1;
}
return log_open(l);
}
/**
* log_commit - commit a log message
@ -121,6 +171,22 @@ log_commit(int class, buffer *buf)
{
byte tbuf[TM_DATETIME_BUFFER_SIZE];
tm_format_real_time(tbuf, config->tf_log.fmt1, current_real_time());
if (l->limit)
{
off_t msg_len = strlen(tbuf) + strlen(class_names[class]) +
(buf->pos - buf->start) + 5;
if (l->pos < 0)
l->pos = log_size(l);
if (l->pos + msg_len > l->limit)
if (log_rotate(l) < 0)
continue;
l->pos += msg_len;
}
fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
}
fputs(buf->start, l->fh);
@ -279,12 +345,26 @@ default_log_list(int debug, int init, char **syslog_name)
}
void
log_switch(int debug, list *l, char *new_syslog_name)
log_switch(int debug, list *logs, char *new_syslog_name)
{
if (!l || EMPTY_LIST(*l))
l = default_log_list(debug, !l, &new_syslog_name);
struct log_config *l;
current_log_list = l;
if (!logs || EMPTY_LIST(*logs))
logs = default_log_list(debug, !logs, &new_syslog_name);
/* Close the logs to avoid pinning them on disk when deleted */
if (current_log_list)
WALK_LIST(l, *current_log_list)
if (l->rf)
log_close(l);
/* Reopen the logs, needed for 'configure undo' */
if (logs)
WALK_LIST(l, *logs)
if (l->filename && !l->rf)
log_open(l);
current_log_list = logs;
#ifdef HAVE_SYSLOG_H
if (current_syslog_name && new_syslog_name &&

View File

@ -14,6 +14,7 @@
struct pool;
struct iface;
struct birdsock;
struct rfile;
/* main.c */
@ -102,7 +103,9 @@ void io_init(void);
void io_loop(void);
void io_log_dump(void);
int sk_open_unix(struct birdsock *s, char *name);
void *tracked_fopen(struct pool *, char *name, char *mode);
struct rfile *rf_open(struct pool *, char *name, char *mode);
void *rf_file(struct rfile *f);
int rf_fileno(struct rfile *f);
void test_old_bird(char *path);
/* krt.c bits */
@ -119,6 +122,11 @@ struct log_config {
node n;
uint mask; /* Classes to log */
void *fh; /* FILE to log to, NULL=syslog */
struct rfile *rf; /* Resource for log file */
char *filename; /* Log filename */
char *backup; /* Secondary filename (for log rotation) */
off_t pos; /* Position/size of current log */
off_t limit; /* Log size limit */
int terminal_flag;
};