diff options
Diffstat (limited to 'bgpd/bgp_attr.c')
-rw-r--r-- | bgpd/bgp_attr.c | 245 |
1 files changed, 134 insertions, 111 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index f34e6493..bc39f3b8 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -153,7 +153,6 @@ cluster_free (struct cluster_list *cluster) XFREE (MTYPE_CLUSTER, cluster); } -#if 0 static struct cluster_list * cluster_dup (struct cluster_list *cluster) { @@ -172,7 +171,6 @@ cluster_dup (struct cluster_list *cluster) return new; } -#endif static struct cluster_list * cluster_intern (struct cluster_list *cluster) @@ -322,6 +320,23 @@ transit_free (struct transit *transit) XFREE (MTYPE_TRANSIT, transit); } +static struct transit * +transit_dup (struct transit *transit) +{ + struct transit *new; + + new = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit)); + new->length = transit->length; + if (new->length) + { + new->val = XMALLOC (MTYPE_TRANSIT_VAL, transit->length); + memcpy (new->val, transit->val, transit->length); + } + else + new->val = NULL; + + return new; +} static void * transit_hash_alloc (void *p) @@ -458,6 +473,46 @@ bgp_attr_dup (struct attr *new, struct attr *orig) } } +void +bgp_attr_deep_dup (struct attr *new, struct attr *orig) +{ + if (orig->aspath) + new->aspath = aspath_dup(orig->aspath); + + if (orig->community) + new->community = community_dup(orig->community); + + if (orig->extra) + { + if (orig->extra->ecommunity) + new->extra->ecommunity = ecommunity_dup(orig->extra->ecommunity); + if (orig->extra->cluster) + new->extra->cluster = cluster_dup(orig->extra->cluster); + if (orig->extra->transit) + new->extra->transit = transit_dup(orig->extra->transit); + } +} + +void +bgp_attr_deep_free (struct attr *attr) +{ + if (attr->aspath) + aspath_free(attr->aspath); + + if (attr->community) + community_free(attr->community); + + if (attr->extra) + { + if (attr->extra->ecommunity) + ecommunity_free(&attr->extra->ecommunity); + if (attr->extra->cluster) + cluster_free(attr->extra->cluster); + if (attr->extra->transit) + transit_free(attr->extra->transit); + } +} + unsigned long int attr_count (void) { @@ -495,6 +550,7 @@ attrhash_key_make (void *p) MIX(extra->weight); MIX(extra->mp_nexthop_global_in.s_addr); MIX(extra->originator_id.s_addr); + MIX(extra->tag); } if (attr->aspath) @@ -540,6 +596,7 @@ attrhash_cmp (const void *p1, const void *p2) && ae1->aggregator_as == ae2->aggregator_as && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr && ae1->weight == ae2->weight + && ae1->tag == ae2->tag && ae1->mp_nexthop_len == ae2->mp_nexthop_len && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global) && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local) @@ -691,6 +748,7 @@ bgp_attr_default_set (struct attr *attr, u_char origin) attr->aspath = aspath_empty (); attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT; + attr->extra->tag = 0; attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN; @@ -717,10 +775,12 @@ bgp_attr_default_intern (u_char origin) return new; } +/* Create the attributes for an aggregate */ struct attr * bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin, struct aspath *aspath, - struct community *community, int as_set) + struct community *community, int as_set, + u_char atomic_aggregate) { struct attr attr; struct attr *new; @@ -753,7 +813,7 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin, attre.weight = BGP_ATTR_DEFAULT_WEIGHT; attre.mp_nexthop_len = IPV6_MAX_BYTELEN; - if (! as_set) + if (! as_set || atomic_aggregate) attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)) @@ -962,19 +1022,18 @@ bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args, CHECK_FLAG (real_flags, attr_flag_str[i].key) ) { - zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"", - LOOKUP (attr_str, attr_code), - CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not", - attr_flag_str[i].str); + zlog_err ("%s attribute must%s be flagged as \"%s\"", + LOOKUP (attr_str, attr_code), + CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not", + attr_flag_str[i].str); seen = 1; } if (!seen) { - zlog (args->peer->log, LOG_DEBUG, - "Strange, %s called for attr %s, but no problem found with flags" - " (real flags 0x%x, desired 0x%x)", - __func__, LOOKUP (attr_str, attr_code), - real_flags, desired_flags); + zlog_debug ("Strange, %s called for attr %s, but no problem found with flags" + " (real flags 0x%x, desired 0x%x)", + __func__, LOOKUP (attr_str, attr_code), + real_flags, desired_flags); } } @@ -1007,7 +1066,6 @@ bgp_attr_flag_invalid (struct bgp_attr_parser_args *args) u_int8_t mask = BGP_ATTR_FLAG_EXTLEN; const u_int8_t flags = args->flags; const u_int8_t attr_code = args->type; - struct peer *const peer = args->peer; /* there may be attributes we don't know about */ if (attr_code > attr_flags_values_max) @@ -1021,9 +1079,8 @@ bgp_attr_flag_invalid (struct bgp_attr_parser_args *args) if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags) && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags)) { - zlog (peer->log, LOG_ERR, - "%s well-known attributes must have transitive flag set (%x)", - LOOKUP (attr_str, attr_code), flags); + zlog_err ("%s well-known attributes must have transitive flag set (%x)", + LOOKUP (attr_str, attr_code), flags); return 1; } @@ -1034,19 +1091,17 @@ bgp_attr_flag_invalid (struct bgp_attr_parser_args *args) { if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)) { - zlog (peer->log, LOG_ERR, - "%s well-known attribute " - "must NOT have the partial flag set (%x)", - LOOKUP (attr_str, attr_code), flags); + zlog_err ("%s well-known attribute " + "must NOT have the partial flag set (%x)", + LOOKUP (attr_str, attr_code), flags); return 1; } if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL) && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)) { - zlog (peer->log, LOG_ERR, - "%s optional + transitive attribute " - "must NOT have the partial flag set (%x)", - LOOKUP (attr_str, attr_code), flags); + zlog_err ("%s optional + transitive attribute " + "must NOT have the partial flag set (%x)", + LOOKUP (attr_str, attr_code), flags); return 1; } } @@ -1081,8 +1136,7 @@ bgp_attr_origin (struct bgp_attr_parser_args *args) value). */ if (length != 1) { - zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d", - length); + zlog_err ("Origin attribute length is not one %d", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1098,8 +1152,7 @@ bgp_attr_origin (struct bgp_attr_parser_args *args) && (attr->origin != BGP_ORIGIN_EGP) && (attr->origin != BGP_ORIGIN_INCOMPLETE)) { - zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d", - attr->origin); + zlog_err ("Origin attribute value is invalid %d", attr->origin); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_INVAL_ORIGIN, args->total); @@ -1130,9 +1183,7 @@ bgp_attr_aspath (struct bgp_attr_parser_args *args) /* In case of IBGP, length will be zero. */ if (! attr->aspath) { - zlog (peer->log, LOG_ERR, - "Malformed AS path from %s, length is %d", - peer->host, length); + zlog_err ("Malformed AS path from %s, length is %d", peer->host, length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0); } @@ -1159,7 +1210,7 @@ bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr) if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) || (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath))) { - zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host); + zlog_err ("Malformed AS path from %s", peer->host); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_AS_PATH); return BGP_ATTR_PARSE_ERROR; @@ -1171,8 +1222,7 @@ bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr) if (peer->sort == BGP_PEER_EBGP && ! aspath_firstas_check (attr->aspath, peer->as)) { - zlog (peer->log, LOG_ERR, - "%s incorrect first AS (must be %u)", peer->host, peer->as); + zlog_err ("%s incorrect first AS (must be %u)", peer->host, peer->as); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MAL_AS_PATH); return BGP_ATTR_PARSE_ERROR; @@ -1206,9 +1256,7 @@ bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path) /* In case of IBGP, length will be zero. */ if (!*as4_path) { - zlog (peer->log, LOG_ERR, - "Malformed AS4 path from %s, length is %d", - peer->host, length); + zlog_err ("Malformed AS4 path from %s, length is %d", peer->host, length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0); @@ -1234,8 +1282,7 @@ bgp_attr_nexthop (struct bgp_attr_parser_args *args) /* Check nexthop attribute length. */ if (length != 4) { - zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]", - length); + zlog_err ("Nexthop attribute length isn't four [%d]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -1253,7 +1300,7 @@ bgp_attr_nexthop (struct bgp_attr_parser_args *args) { char buf[INET_ADDRSTRLEN]; inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN); - zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf); + zlog_err ("Martian nexthop %s", buf); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, args->total); @@ -1276,8 +1323,7 @@ bgp_attr_med (struct bgp_attr_parser_args *args) /* Length check. */ if (length != 4) { - zlog (peer->log, LOG_ERR, - "MED attribute length isn't four [%d]", length); + zlog_err ("MED attribute length isn't four [%d]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -1302,8 +1348,7 @@ bgp_attr_local_pref (struct bgp_attr_parser_args *args) /* Length check. */ if (length != 4) { - zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]", - length); + zlog_err ("LOCAL_PREF attribute length isn't 4 [%u]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1330,15 +1375,13 @@ bgp_attr_local_pref (struct bgp_attr_parser_args *args) static int bgp_attr_atomic (struct bgp_attr_parser_args *args) { - struct peer *const peer = args->peer; struct attr *const attr = args->attr; const bgp_size_t length = args->length; /* Length check. */ if (length != 0) { - zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]", - length); + zlog_err ("ATOMIC_AGGREGATE attribute length isn't 0 [%u]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1367,8 +1410,7 @@ bgp_attr_aggregator (struct bgp_attr_parser_args *args) if (length != wantedlen) { - zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]", - wantedlen, length); + zlog_err ("AGGREGATOR attribute length isn't %u [%u]", wantedlen, length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1398,8 +1440,7 @@ bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args, if (length != 8) { - zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]", - length); + zlog_err ("New Aggregator length is not 8 [%d]", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 0); @@ -1562,7 +1603,7 @@ bgp_attr_originator_id (struct bgp_attr_parser_args *args) /* Length check. */ if (length != 4) { - zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length); + zlog_err ("Bad originator ID length %d", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, @@ -1588,7 +1629,7 @@ bgp_attr_cluster_list (struct bgp_attr_parser_args *args) /* Check length. */ if (length % 4) { - zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length); + zlog_err ("Bad cluster list length %d", length); return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, args->total); @@ -1698,8 +1739,8 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args, char buf1[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN]; - if (BGP_DEBUG (update, UPDATE_IN)) - zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host, + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug ("%s sent two nexthops %s %s but second one is not a link-local nexthop", peer->host, inet_ntop (AF_INET6, &attre->mp_nexthop_global, buf1, INET6_ADDRSTRLEN), inet_ntop (AF_INET6, &attre->mp_nexthop_local, @@ -1736,7 +1777,7 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args, __func__, peer->host); return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; } - + mp_update->afi = afi; mp_update->safi = safi; mp_update->nlri = stream_pnt (s); @@ -1837,8 +1878,7 @@ bgp_attr_encap( if (!CHECK_FLAG(flag, BGP_ATTR_FLAG_TRANS) || !CHECK_FLAG(flag, BGP_ATTR_FLAG_OPTIONAL)) { - zlog (peer->log, LOG_ERR, - "Tunnel Encap attribute flag isn't optional and transitive %d", flag); + zlog_err ("Tunnel Encap attribute flag isn't optional and transitive %d", flag); bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, @@ -1851,8 +1891,7 @@ bgp_attr_encap( uint16_t tlv_length; if (length < 4) { - zlog (peer->log, LOG_ERR, - "Tunnel Encap attribute not long enough to contain outer T,L"); + zlog_err ("Tunnel Encap attribute not long enough to contain outer T,L"); bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, @@ -1864,7 +1903,7 @@ bgp_attr_encap( length -= 4; if (tlv_length != length) { - zlog (peer->log, LOG_ERR, "%s: tlv_length(%d) != length(%d)", + zlog_err ("%s: tlv_length(%d) != length(%d)", __func__, tlv_length, length); } } @@ -1881,8 +1920,7 @@ bgp_attr_encap( } if (sublength > length) { - zlog (peer->log, LOG_ERR, - "Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d", + zlog_err ("Tunnel Encap attribute sub-tlv length %d exceeds remaining length %d", sublength, length); bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, @@ -1923,8 +1961,7 @@ bgp_attr_encap( if (length) { /* spurious leftover data */ - zlog (peer->log, LOG_ERR, - "Tunnel Encap attribute length is bad: %d leftover octets", length); + zlog_err ("Tunnel Encap attribute length is bad: %d leftover octets", length); bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, @@ -1949,15 +1986,10 @@ bgp_attr_unknown (struct bgp_attr_parser_args *args) const u_char flag = args->flags; const bgp_size_t length = args->length; - - if (BGP_DEBUG (normal, NORMAL)) - zlog_debug ("%s Unknown attribute is received (type %d, length %d)", - peer->host, type, length); + if (bgp_debug_update(peer, NULL, 1)) + zlog_debug ("%s Unknown attribute is received (type %d, length %d)", + peer->host, type, length); - if (BGP_DEBUG (events, EVENTS)) - zlog (peer->log, LOG_DEBUG, - "Unknown attribute type %d length %d is received", type, length); - /* Forward read pointer of input stream. */ stream_forward_getp (peer->ibuf, length); @@ -2039,9 +2071,7 @@ bgp_attr_check (struct peer *peer, struct attr *attr) if (type) { - zlog (peer->log, LOG_WARNING, - "%s Missing well-known attribute %d / %s", - peer->host, type, LOOKUP (attr_str, type)); + zlog_warn ("%s Missing well-known attribute %d.", peer->host, type); bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_MISS_ATTR, @@ -2083,10 +2113,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN) { /* XXX warning: long int format, int arg (arg 5) */ - zlog (peer->log, LOG_WARNING, - "%s: error BGP attribute length %lu is smaller than min len", - peer->host, - (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); + zlog_warn ("%s: error BGP attribute length %lu is smaller than min len", + peer->host, + (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, @@ -2106,10 +2135,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) { - zlog (peer->log, LOG_WARNING, - "%s: Extended length set, but just %lu bytes of attr header", - peer->host, - (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); + zlog_warn ("%s: Extended length set, but just %lu bytes of attr header", + peer->host, + (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, @@ -2129,9 +2157,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (CHECK_BITMAP (seen, type)) { - zlog (peer->log, LOG_WARNING, - "%s: error BGP attribute type %d appears twice in a message", - peer->host, type); + zlog_warn ("%s: error BGP attribute type %d appears twice in a message", + peer->host, type); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, @@ -2149,11 +2176,11 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (attr_endp > endp) { - zlog (peer->log, LOG_WARNING, - "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp); - bgp_notify_send (peer, - BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); + zlog_warn ("%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp); + bgp_notify_send_with_data (peer, + BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + startp, attr_endp - startp); return BGP_ATTR_PARSE_ERROR; } @@ -2252,10 +2279,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, /* If hard error occured immediately return to the caller. */ if (ret == BGP_ATTR_PARSE_ERROR) { - zlog (peer->log, LOG_WARNING, - "%s: Attribute %s, parse error", - peer->host, - LOOKUP (attr_str, type)); + zlog_warn ("%s: Attribute %s, parse error", + peer->host, + LOOKUP (attr_str, type)); if (as4_path) aspath_unintern (&as4_path); return ret; @@ -2263,10 +2289,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, if (ret == BGP_ATTR_PARSE_WITHDRAW) { - zlog (peer->log, LOG_WARNING, - "%s: Attribute %s, parse error - treating as withdrawal", - peer->host, - LOOKUP (attr_str, type)); + zlog_warn ("%s: Attribute %s, parse error - treating as withdrawal", + peer->host, + LOOKUP (attr_str, type)); if (as4_path) aspath_unintern (&as4_path); return ret; @@ -2275,9 +2300,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, /* Check the fetched length. */ if (BGP_INPUT_PNT (peer) != attr_endp) { - zlog (peer->log, LOG_WARNING, - "%s: BGP attribute %s, fetch error", - peer->host, LOOKUP (attr_str, type)); + zlog_warn ("%s: BGP attribute %s, fetch error", + peer->host, LOOKUP (attr_str, type)); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); @@ -2289,9 +2313,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, /* Check final read pointer is same as end pointer. */ if (BGP_INPUT_PNT (peer) != endp) { - zlog (peer->log, LOG_WARNING, - "%s: BGP attribute %s, length mismatch", - peer->host, LOOKUP (attr_str, type)); + zlog_warn ("%s: BGP attribute %s, length mismatch", + peer->host, LOOKUP (attr_str, type)); bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); @@ -2547,8 +2570,7 @@ bgp_packet_mpattr_tea( } if (attrlenfield > 0xffff) { - zlog (peer->log, LOG_ERR, - "%s attribute is too long (length=%d), can't send it", + zlog_err ("%s attribute is too long (length=%d), can't send it", attrname, attrlenfield); return; @@ -2705,12 +2727,13 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, } /* MED attribute. */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC) || + bgp->maxmed_active) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC); stream_putc (s, 4); - stream_putl (s, attr->med); + stream_putl (s, (bgp->maxmed_active ? bgp->maxmed_value : attr->med)); } /* Local preference. */ |