*/
static uint16_t bgp_read(struct peer *peer)
{
- size_t readsize; // how many bytes we want to read
ssize_t nbytes; // how many bytes we actually read
uint16_t status = 0;
- uint8_t ibw[peer->max_packet_size * BGP_READ_PACKET_MAX];
- readsize = MIN(ringbuf_space(peer->ibuf_work), sizeof(ibw));
- nbytes = read(peer->fd, ibw, readsize);
+ nbytes = ringbuf_read(peer->ibuf_work, peer->fd);
/* EAGAIN or EWOULDBLOCK; come back later */
if (nbytes < 0 && ERRNO_IO_RETRY(errno)) {
BGP_EVENT_ADD(peer, TCP_connection_closed);
SET_FLAG(status, BGP_IO_FATAL_ERR);
- } else {
- assert(ringbuf_put(peer->ibuf_work, ibw, nbytes)
- == (size_t)nbytes);
}
return status;
(struct bgp_node *rn, struct bgp_path_info *pi, bool added),
(rn, pi, added))
+DEFINE_HOOK(bgp_rpki_prefix_status,
+ (struct peer *peer, struct attr *attr,
+ const struct prefix *prefix),
+ (peer, attr, prefix))
+
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
return "n/a";
}
+static const char *bgp_rpki_validation2str(int v_state)
+{
+ switch (v_state) {
+ case 1:
+ return "valid";
+ case 2:
+ return "not found";
+ case 3:
+ return "invalid";
+ default:
+ break;
+ }
+ return "ERROR";
+}
+
int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
safi_t safi, char *errmsg, size_t errmsg_len)
{
int i;
char *nexthop_hostname =
bgp_nexthop_hostname(path->peer, path->nexthop);
+ int rpki_validation_state = 0;
if (json_paths) {
json_path = json_object_new_object();
}
}
+ const struct prefix *p = bgp_dest_get_prefix(bn);
+ if (p->family == AF_INET || p->family == AF_INET6)
+ rpki_validation_state = hook_call(bgp_rpki_prefix_status,
+ path->peer, path->attr, p);
+ if (rpki_validation_state) {
+ if (json_paths)
+ json_object_string_add(
+ json_path, "rpkiValidationState",
+ bgp_rpki_validation2str(rpki_validation_state));
+ else
+ vty_out(vty, ", validation-state: %s",
+ bgp_rpki_validation2str(rpki_validation_state));
+ }
+
if (json_bestpath)
json_object_object_add(json_path, "bestpath", json_bestpath);
{
lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper);
+ hook_register(bgp_rpki_prefix_status, rpki_validate_prefix);
hook_register(frr_late_init, bgp_rpki_init);
hook_register(frr_early_fini, &bgp_rpki_fini);
DECLARE_HOOK(bgp_snmp_update_stats,
(struct bgp_node *rn, struct bgp_path_info *pi, bool added),
(rn, pi, added))
+DECLARE_HOOK(bgp_rpki_prefix_status,
+ (struct peer * peer, struct attr *attr,
+ const struct prefix *prefix),
+ (peer, attr, prefix))
+
void peer_nsf_stop(struct peer *peer);
#endif /* _QUAGGA_BGPD_H */
/* Handle notification about route being added */
void isis_redist_add(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p, uint8_t distance,
- uint32_t metric)
+ uint32_t metric, const route_tag_t tag)
{
int family = p->family;
struct route_table *ei_table = get_ext_info(isis, family);
info->origin = type;
info->distance = distance;
info->metric = metric;
+ info->tag = tag;
if (is_default_prefix(p)
&& (!src_p || !src_p->prefixlen)) {
* "always" setting will ignore routes with origin
* DEFAULT_ROUTE. */
isis_redist_add(isis, DEFAULT_ROUTE, p, NULL, 254,
- MAX_WIDE_PATH_METRIC);
+ MAX_WIDE_PATH_METRIC, 0);
return;
}
int origin;
uint32_t metric;
uint8_t distance;
+ route_tag_t tag;
};
struct isis_redist {
int level);
void isis_redist_add(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p, uint8_t distance,
- uint32_t metric);
+ uint32_t metric, route_tag_t tag);
void isis_redist_delete(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p);
int isis_redist_config_write(struct vty *vty, struct isis_area *area,
/* ------------------------------------------------------------*/
+/* `match tag TAG' */
+/* Match function return 1 if match is success else return zero. */
+static enum route_map_cmd_result_t
+route_match_tag(void *rule, const struct prefix *p, void *object)
+{
+ route_tag_t *tag;
+ struct isis_ext_info *info;
+ route_tag_t info_tag;
+
+ tag = rule;
+ info = object;
+
+ info_tag = info->tag;
+ if (info_tag == *tag)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
+}
+
+/* Route map commands for tag matching. */
+static const struct route_map_rule_cmd route_match_tag_cmd = {
+ "tag",
+ route_match_tag,
+ route_map_rule_tag_compile,
+ route_map_rule_tag_free,
+};
+
+/* ------------------------------------------------------------*/
+
static enum route_map_cmd_result_t
route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
{
route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
+ route_map_match_tag_hook(generic_match_add);
+ route_map_no_match_tag_hook(generic_match_delete);
+
route_map_set_metric_hook(generic_set_add);
route_map_no_set_metric_hook(generic_set_delete);
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
route_map_install_match(&route_match_ipv6_address_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
+ route_map_install_match(&route_match_tag_cmd);
route_map_install_set(&route_set_metric_cmd);
}
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix,
- api.distance, api.metric);
+ api.distance, api.metric, api.tag);
else
isis_redist_delete(isis, api.type, &api.prefix,
&api.src_prefix);
memset(buf->data, 0x00, buf->size);
ringbuf_reset(buf);
}
+
+ssize_t ringbuf_read(struct ringbuf *buf, int sock)
+{
+ size_t to_read = ringbuf_space(buf);
+ size_t bytes_to_end = buf->size - buf->end;
+ ssize_t bytes_read;
+ struct iovec iov[2] = {};
+
+ /* Calculate amount of read blocks. */
+ if (to_read > bytes_to_end) {
+ iov[0].iov_base = buf->data + buf->end;
+ iov[0].iov_len = bytes_to_end;
+ iov[1].iov_base = buf->data;
+ iov[1].iov_len = to_read - bytes_to_end;
+ } else {
+ iov[0].iov_base = buf->data + buf->end;
+ iov[0].iov_len = to_read;
+ }
+
+ /* Do the system call. */
+ bytes_read = readv(sock, iov, 2);
+ if (bytes_read <= 0)
+ return bytes_read;
+
+ /* Calculate the new end. */
+ if ((size_t)bytes_read > bytes_to_end)
+ buf->end = bytes_read - bytes_to_end;
+ else
+ buf->end += bytes_read;
+
+ /* Set emptiness state. */
+ buf->empty = (buf->start == buf->end) && (buf->empty && !bytes_read);
+
+ return bytes_read;
+}
*/
void ringbuf_wipe(struct ringbuf *buf);
+/**
+ * Perform a socket/file `read()` in to the ring buffer.
+ *
+ * \param buf the ring buffer pointer.
+ * \param sock the file descriptor.
+ * \returns the number of bytes read, `0` on connection close or `-1` with
+ * `errno` pointing the error (see `readv()` man page for more
+ * information.)
+ */
+ssize_t ringbuf_read(struct ringbuf *buf, int sock);
+
#ifdef __cplusplus
}
#endif
if (IS_AREA_STUB(area)) {
if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
- zlog_debug("Stubbing out area for if %s", area->name);
+ zlog_debug("Stubbing out area for area %s", area->name);
OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
+ ospf6_asbr_remove_externals_from_area(area);
} else if (IS_AREA_ENABLED(area)) {
if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
- zlog_debug("Normal area for if %s", area->name);
+ zlog_debug("Normal area for area %s", area->name);
OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
ospf6_asbr_send_externals_to_area(area);
}
}
}
+/* When an area is stubified, remove all the external LSAs in the area */
+void ospf6_asbr_remove_externals_from_area(struct ospf6_area *oa)
+{
+ struct ospf6_lsa *lsa, *lsanext;
+ struct listnode *node, *nnode;
+ struct ospf6_area *area;
+ struct ospf6 *ospf6 = oa->ospf6;
+
+
+ /* skip if router is in other non-stub areas */
+ for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area))
+ if (!IS_AREA_STUB(area))
+ return;
+
+ /* if router is only in a stub area then purge AS-External LSAs */
+ for (ALL_LSDB(oa->ospf6->lsdb, lsa, lsanext)) {
+ if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL)
+ ospf6_lsdb_remove(lsa, ospf6->lsdb);
+ }
+}
+
void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct prefix *prefix,
unsigned int nexthop_num,
extern void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6);
extern void ospf6_asbr_terminate(void);
extern void ospf6_asbr_send_externals_to_area(struct ospf6_area *);
+extern void ospf6_asbr_remove_externals_from_area(struct ospf6_area *oa);
extern int config_write_ospf6_debug_asbr(struct vty *vty);
extern void install_element_ospf6_debug_asbr(void);
so that ospf6_send_dbdesc () can send those LSAs */
size = sizeof(struct ospf6_lsa_header) + sizeof(struct ospf6_dbdesc);
for (ALL_LSDB(on->summary_list, lsa, lsanext)) {
+ /* if stub area then don't advertise AS-External LSAs */
+ if (IS_AREA_STUB(on->ospf6_if->area)
+ && ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) {
+ ospf6_lsdb_remove(lsa, on->summary_list);
+ continue;
+ }
+
if (size + sizeof(struct ospf6_lsa_header)
> ospf6_packet_max(on->ospf6_if)) {
ospf6_lsdb_lsa_unlock(lsa);
logger.error(errormsg)
return False
- try:
- community_type = int(community_type)
- cmd = "{} {} {} {}".format(cmd, community_type, action, value)
- except ValueError:
-
- cmd = "{} {} {} {} {}".format(
- cmd, community_type, name, action, value
- )
+ cmd = "{} {} {} {} {}".format(cmd, community_type, name, action, value)
if del_action:
cmd = "no {}".format(cmd)