return false;
}
-static void stream_put_bgp_aigp_tlv_metric(struct stream *s,
- struct bgp_path_info *bpi)
+static void stream_put_bgp_aigp_tlv_metric(struct stream *s, uint64_t aigp)
{
stream_putc(s, BGP_AIGP_TLV_METRIC);
stream_putw(s, BGP_AIGP_TLV_METRIC_LEN);
- stream_putq(s, bgp_aigp_metric_total(bpi));
+ stream_putq(s, aigp);
}
static bool bgp_attr_aigp_valid(uint8_t *pnt, int length)
}
/* Make attribute packet. */
-bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
- struct stream *s, struct attr *attr,
- struct bpacket_attr_vec_arr *vecarr,
- struct prefix *p, afi_t afi, safi_t safi,
- struct peer *from, struct prefix_rd *prd,
- mpls_label_t *label, uint8_t num_labels,
- bool addpath_capable, uint32_t addpath_tx_id,
- struct bgp_path_info *bpi)
+bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct stream *s,
+ struct attr *attr, struct bpacket_attr_vec_arr *vecarr,
+ struct prefix *p, afi_t afi, safi_t safi, struct peer *from,
+ struct prefix_rd *prd, mpls_label_t *label, uint8_t num_labels,
+ bool addpath_capable, uint32_t addpath_tx_id)
{
size_t cp;
size_t aspath_sizep;
}
/* AIGP */
- if (bpi && CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
- (CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
- peer->sub_sort == BGP_PEER_EBGP_OAD ||
- peer->sort != BGP_PEER_EBGP)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && AIGP_TRANSMIT_ALLOWED(peer)) {
/* At the moment only AIGP Metric TLV exists for AIGP
* attribute. If more comes in, do not forget to update
* attr_len variable to include new ones.
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, BGP_ATTR_AIGP);
stream_putc(s, attr_len);
- stream_put_bgp_aigp_tlv_metric(s, bpi);
+ stream_put_bgp_aigp_tlv_metric(s, attr->aigp_metric);
}
/* Unknown transit attribute. */
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_AIGP);
stream_putc(s, attr_len);
- stream_put_bgp_aigp_tlv_metric(s, bpi);
+ stream_put_bgp_aigp_tlv_metric(s, attr->aigp_metric);
}
/* Return total size of attribute. */
struct community *community, struct ecommunity *ecommunity,
struct lcommunity *lcommunity, struct bgp_aggregate *aggregate,
uint8_t atomic_aggregate, const struct prefix *p);
-extern bgp_size_t bgp_packet_attribute(
- struct bgp *bgp, struct peer *peer, struct stream *s, struct attr *attr,
- struct bpacket_attr_vec_arr *vecarr, struct prefix *p, afi_t afi,
- safi_t safi, struct peer *from, struct prefix_rd *prd,
- mpls_label_t *label, uint8_t num_labels, bool addpath_capable,
- uint32_t addpath_tx_id, struct bgp_path_info *bpi);
+extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, struct stream *s,
+ struct attr *attr, struct bpacket_attr_vec_arr *vecarr,
+ struct prefix *p, afi_t afi, safi_t safi, struct peer *from,
+ struct prefix_rd *prd, mpls_label_t *label,
+ uint8_t num_labels, bool addpath_capable,
+ uint32_t addpath_tx_id);
extern void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
const struct prefix *p);
extern bool attrhash_cmp(const void *arg1, const void *arg2);
attr->transit = transit;
}
+#define AIGP_TRANSMIT_ALLOWED(peer) \
+ (CHECK_FLAG((peer)->flags, PEER_FLAG_AIGP) || ((peer)->sub_sort == BGP_PEER_EBGP_OAD) || \
+ ((peer)->sort != BGP_PEER_EBGP))
+
static inline uint64_t bgp_attr_get_aigp_metric(const struct attr *attr)
{
return attr->aigp_metric;
stream_putw(s, 0);
/* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
- total_attr_len =
- bgp_packet_attribute(NULL, peer, s, attr, &vecarr, NULL, afi,
- safi, peer, NULL, NULL, 0, 0, 0, NULL);
+ total_attr_len = bgp_packet_attribute(NULL, peer, s, attr, &vecarr, NULL, afi, safi, peer,
+ NULL, NULL, 0, 0, 0);
/* space check? */
false));
}
+ /*
+ * Adjust AIGP for propagation when the nexthop is set to ourselves,
+ * e.g., using "set ip nexthop peer-address" or when advertising to
+ * EBGP. Note in route reflection the nexthop is usually unmodified
+ * and the AIGP should not be adjusted in that case.
+ */
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && AIGP_TRANSMIT_ALLOWED(peer)) {
+ if (nh_reset ||
+ CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS)) {
+ uint64_t aigp = bgp_aigp_metric_total(pi);
+
+ bgp_attr_set_aigp_metric(attr, aigp);
+ }
+ }
+
return true;
}
/* 5: Encode all the attributes, except MP_REACH_NLRI
* attr. */
- total_attr_len = bgp_packet_attribute(
- NULL, peer, s, adv->baa->attr, &vecarr, NULL,
- afi, safi, from, NULL, NULL, 0, 0, 0, path);
+ total_attr_len = bgp_packet_attribute(NULL, peer, s, adv->baa->attr,
+ &vecarr, NULL, afi, safi, from, NULL,
+ NULL, 0, 0, 0);
space_remaining =
STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s))
/* Make place for total attribute length. */
pos = stream_get_endp(s);
stream_putw(s, 0);
- total_attr_len =
- bgp_packet_attribute(NULL, peer, s, attr, &vecarr, &p, afi,
- safi, from, NULL, &label, num_labels,
- addpath_capable,
- BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE,
- NULL);
+ total_attr_len = bgp_packet_attribute(NULL, peer, s, attr, &vecarr, &p, afi, safi, from,
+ NULL, &label, num_labels, addpath_capable,
+ BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
/* Set Total Path Attribute Length. */
stream_putw_at(s, pos, total_attr_len);