/******************************************************************************* 函数名称 : bgp_info_mpath_aggregate_update 功能描述 : mpath聚合路由更新 输入参数 : 输出参数 : 返 回 值 : 无 -------------------------------------------------------------------------------- 最近一次修改记录 : 修改作者 : 修改目的 : 新添加函数 修改日期 : 2012-8-15 *******************************************************************************/ void bgp_info_mpath_aggregate_update (struct bgp_info *new_best, struct bgp_info *old_best) { struct bgp_info *mpinfo; struct aspath *aspath; struct aspath *asmerge; struct attr *new_attr, *old_attr; u8 origin, attr_chg; struct community *community, *commerge; struct ecommunity *ecomm, *ecommerge; struct attr_extra *ae; struct attr attr = { 0 }; if (old_best && (old_best != new_best) && (old_attr = bgp_info_mpath_attr (old_best))) { bgp_attr_unintern (&old_attr); bgp_info_mpath_attr_set (old_best, NULL); } if (!new_best) { return; } if (!bgp_info_mpath_count (new_best)) { if ((new_attr = bgp_info_mpath_attr (new_best))) { bgp_attr_unintern (&new_attr); bgp_info_mpath_attr_set (new_best, NULL); SET_FLAG (new_best->flags, BGP_INFO_ATTR_CHANGED); } return; } if (!CHECK_FLAG (new_best->flags, BGP_INFO_MULTIPATH_CHG) && (old_best == new_best)) { attr_chg = 0; if (CHECK_FLAG (new_best->flags, BGP_INFO_ATTR_CHANGED)) { attr_chg = 1; } else { for (mpinfo = bgp_info_mpath_first (new_best); mpinfo; mpinfo = bgp_info_mpath_next (mpinfo)) { if (CHECK_FLAG (mpinfo->flags, BGP_INFO_ATTR_CHANGED)) { attr_chg = 1; break; } } } if (!attr_chg) { return; } } bgp_attr_dup (&attr, new_best->attr); /* aggregate attribute from multipath constituents */ aspath = aspath_dup (attr.aspath); origin = attr.origin; community = attr.community ? community_dup (attr.community) : NULL; ae = attr.extra; ecomm = (ae && ae->ecommunity) ? ecommunity_dup (ae->ecommunity) : NULL; for (mpinfo = bgp_info_mpath_first (new_best); mpinfo; mpinfo = bgp_info_mpath_next (mpinfo)) { asmerge = aspath_aggregate (aspath, mpinfo->attr->aspath); aspath_free (aspath); aspath = asmerge; if (origin < mpinfo->attr->origin) { origin = mpinfo->attr->origin; } if (mpinfo->attr->community) { if (community) { commerge = community_merge (community, mpinfo->attr->community); community = community_uniq_sort (commerge); community_free (&commerge); } else { community = community_dup (mpinfo->attr->community); } } ae = mpinfo->attr->extra; if (ae && ae->ecommunity) { if (ecomm) { ecommerge = ecommunity_merge (ecomm, ae->ecommunity); ecomm = ecommunity_uniq_sort (ecommerge); ecommunity_free (ecommerge); } else { ecomm = ecommunity_dup (ae->ecommunity); } } } attr.aspath = aspath; attr.origin = origin; if (community) { attr.community = community; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); } if (ecomm) { ae = bgp_attr_extra_get (&attr); ae->ecommunity = ecomm; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); } /* Zap multipath attr nexthop so we set nexthop to self */ attr.nexthop.s_addr = 0; #ifdef HAVE_IPV6 if (attr.extra) { memset (&attr.extra->mp_nexthop_global, 0, sizeof (struct in6_addr)); } #endif /* HAVE_IPV6 */ new_attr = bgp_attr_intern (&attr); bgp_attr_extra_free (&attr); if (new_attr != bgp_info_mpath_attr (new_best)) { if ((old_attr = bgp_info_mpath_attr (new_best))) { bgp_attr_unintern (&old_attr); } bgp_info_mpath_attr_set (new_best, new_attr); SET_FLAG (new_best->flags, BGP_INFO_ATTR_CHANGED); } else { bgp_attr_unintern (&new_attr); } }
/* Dump attribute. */ int bgp_dump_attr (struct peer *peer, struct attr *attr, char *buf, size_t size) { if (! attr) return 0; if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))) snprintf (buf, size, "nexthop %s", inet_ntoa (attr->nexthop)); if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN))) snprintf (buf + strlen (buf), size - strlen (buf), ", origin %s", bgp_origin_str[attr->origin]); #ifdef HAVE_IPV6 { char addrbuf[BUFSIZ]; /* Add MP case. */ if (attr->mp_nexthop_len == 16 || attr->mp_nexthop_len == 32) snprintf (buf + strlen (buf), size - strlen (buf), ", mp_nexthop %s", inet_ntop (AF_INET6, &attr->mp_nexthop_global, addrbuf, BUFSIZ)); if (attr->mp_nexthop_len == 32) snprintf (buf + strlen (buf), size - strlen (buf), "(%s)", inet_ntop (AF_INET6, &attr->mp_nexthop_local, addrbuf, BUFSIZ)); } #endif /* HAVE_IPV6 */ if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))) snprintf (buf + strlen (buf), size - strlen (buf), ", localpref %d", attr->local_pref); if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC))) snprintf (buf + strlen (buf), size - strlen (buf), ", metric %d", attr->med); if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))) snprintf (buf + strlen (buf), size - strlen (buf), ", community %s", community_str (attr->community)); if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE))) snprintf (buf + strlen (buf), size - strlen (buf), ", atomic-aggregate"); if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR))) snprintf (buf + strlen (buf), size - strlen (buf), ", aggregated by %d %s", attr->aggregator_as, inet_ntoa (attr->aggregator_addr)); if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID))) snprintf (buf + strlen (buf), size - strlen (buf), ", originator %s", inet_ntoa (attr->originator_id)); if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST))) { int i; snprintf (buf + strlen (buf), size - strlen (buf), ", clusterlist"); for (i = 0; i < attr->cluster->length / 4; i++) snprintf (buf + strlen (buf), size - strlen (buf), " %s", inet_ntoa (attr->cluster->list[i])); } if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))) snprintf (buf + strlen (buf), size - strlen (buf), ", path %s", aspath_print (attr->aspath)); if (strlen (buf) > 1) return 1; else return 0; }
void print_entry(char *cidr, BGPDUMP_ENTRY *entry,std::ofstream &outFile) { char prefix[BGPDUMP_ADDRSTRLEN]; outFile << entry->time << "|"; if (entry->body.zebra_message.withdraw_count) { //withdrawal outFile << "W|"; switch(entry->body.zebra_message.address_family) { case AFI_IP6: inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip.v6_addr,prefix,sizeof(prefix)); outFile << prefix << "|"; break; case AFI_IP: default: if (entry->body.zebra_message.source_ip.v4_addr.s_addr != 0x00000000L) outFile << inet_ntoa(entry->body.zebra_message.source_ip.v4_addr) << "|"; else outFile << "NA|"; } outFile << "AS" << print_asn(entry->body.zebra_message.source_as) << "|"; switch(entry->body.zebra_message.address_family) { case AFI_IP6: inet_ntop(AF_INET6,&entry->body.zebra_message.destination_ip.v6_addr,prefix,sizeof(prefix)); outFile << prefix << "|"; break; case AFI_IP: default: if (entry->body.zebra_message.destination_ip.v4_addr.s_addr != 0x00000000L) outFile << inet_ntoa(entry->body.zebra_message.destination_ip.v4_addr) << "|"; else outFile << "NA|"; } outFile << "AS" << print_asn(entry->body.zebra_message.destination_as) << "|"; outFile << cidr << std::endl; } else if ((entry->body.zebra_message.announce_count) || (entry->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI))) { //announce outFile << "A|"; switch(entry->body.zebra_message.address_family) { case AFI_IP6: inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip.v6_addr,prefix,sizeof(prefix)); outFile << prefix << "|"; break; case AFI_IP: default: if (entry->body.zebra_message.source_ip.v4_addr.s_addr != 0x00000000L) outFile << inet_ntoa(entry->body.zebra_message.source_ip.v4_addr) << "|"; else outFile << "NA|"; } outFile << "AS" << print_asn(entry->body.zebra_message.source_as) << "|"; switch(entry->body.zebra_message.address_family) { case AFI_IP6: inet_ntop(AF_INET6,&entry->body.zebra_message.destination_ip.v6_addr,prefix,sizeof(prefix)); outFile << prefix << "|"; break; case AFI_IP: default: if (entry->body.zebra_message.destination_ip.v4_addr.s_addr != 0x00000000L) outFile << inet_ntoa(entry->body.zebra_message.destination_ip.v4_addr) << "|"; else outFile << "NA|"; } outFile << "AS" << print_asn(entry->body.zebra_message.destination_as) << "|"; outFile << cidr << "|"; if (entry->attr->aspath != NULL) outFile << entry->attr->aspath->str; outFile << std::endl; } }
void process_attr_read(struct mstream *s, struct attr *attr, u_int8_t asn_len, struct zebra_incomplete *incomplete, char mp_only_nexthop) { u_char flag; u_char type; u_int32_t len, end; u_int32_t truelen; struct unknown_attr *unknown; mstream_getw(s, &attr->len); if(attr->len == 0) return; attr->data=malloc(attr->len); /* Check the attributes are not truncated */ if(attr->len > mstream_can_read(s)) { truelen = mstream_can_read(s); memset(attr->data + truelen, 0, attr->len - truelen); } else { truelen = attr->len; } memcpy(attr->data, &s->start[s->position], truelen); end = s->position + truelen; while(s->position < end) { mstream_getc(s,&flag); mstream_getc(s,&type); if(flag & BGP_ATTR_FLAG_EXTLEN) len=mstream_getw(s,NULL); else len=mstream_getc(s,NULL); /* Take note of all attributes, including unknown ones */ if(type <= sizeof(attr->flag) * 8) attr->flag = attr->flag | ATTR_FLAG_BIT (type); switch(type) { case BGP_ATTR_ORIGIN: mstream_getc(s,&attr->origin); break; case BGP_ATTR_AS_PATH: attr->aspath = create_aspath(len, asn_len); mstream_get(s,attr->aspath->data,len); process_attr_aspath_string(attr->aspath); break; case BGP_ATTR_NEXT_HOP: mstream_get_ipv4(s,&attr->nexthop.s_addr); break; case BGP_ATTR_MULTI_EXIT_DISC: mstream_getl(s,&attr->med); break; case BGP_ATTR_LOCAL_PREF: mstream_getl(s,&attr->local_pref); break; case BGP_ATTR_ATOMIC_AGGREGATE: break; case BGP_ATTR_AGGREGATOR: read_asn(s, &attr->aggregator_as, asn_len); mstream_get_ipv4(s,&attr->aggregator_addr.s_addr); break; case BGP_ATTR_COMMUNITIES: attr->community = malloc(sizeof(struct community)); attr->community->size = len / 4; attr->community->val = malloc(len); mstream_get(s,attr->community->val,len); attr->community->str = NULL; process_attr_community_string(attr->community); break; case BGP_ATTR_MP_REACH_NLRI: if(attr->mp_info == NULL) { attr->mp_info = malloc(sizeof(struct mp_info)); memset(attr->mp_info, 0, sizeof(struct mp_info)); } if(mp_only_nexthop) process_mp_announce_only_nexthop(s, attr->mp_info, len, incomplete); else process_mp_announce(s, attr->mp_info, len, incomplete); break; case BGP_ATTR_MP_UNREACH_NLRI: if(attr->mp_info == NULL) { attr->mp_info = malloc(sizeof(struct mp_info)); memset(attr->mp_info, 0, sizeof(struct mp_info)); } process_mp_withdraw(s, attr->mp_info, len, incomplete); case BGP_ATTR_NEW_AS_PATH: attr->new_aspath = create_aspath(len, ASN32_LEN); mstream_get(s,attr->new_aspath->data,len); process_attr_aspath_string(attr->new_aspath); /* AS_CONFED_SEQUENCE and AS_CONFED_SET segments invalid in NEW_AS_PATH */ check_new_aspath(attr->new_aspath); break; case BGP_ATTR_NEW_AGGREGATOR: read_asn(s, &attr->new_aggregator_as, ASN32_LEN); mstream_get_ipv4(s,&attr->new_aggregator_addr.s_addr); break; case BGP_ATTR_ORIGINATOR_ID: mstream_get_ipv4(s,&attr->originator_id.s_addr); break; case BGP_ATTR_CLUSTER_LIST: attr->cluster = malloc(sizeof(struct cluster_list)); attr->cluster->length = len/4; attr->cluster->list = malloc((attr->cluster->length) * sizeof(struct in_addr)); int cluster_index; for (cluster_index=0;cluster_index<attr->cluster->length;cluster_index++) mstream_get_ipv4(s,&attr->cluster->list[cluster_index].s_addr); break; default: /* Unknown attribute. Save as is */ attr->unknown_num++; attr->unknown = realloc(attr->unknown, attr->unknown_num * sizeof(struct unknown_attr)); /* Pointer to the unknown attribute we want to fill in */ unknown = attr->unknown + attr->unknown_num - 1; /* Work around bogus attribute lengths */ if(s->position + len > end) unknown->real_len = end - s->position; else unknown->real_len = len; unknown->flag = flag; unknown->type = type; unknown->len = len; unknown->raw = malloc(unknown->real_len + ((flag & BGP_ATTR_FLAG_EXTLEN) ? 4 : 3)); unknown->raw[0] = flag; unknown->raw[1] = type; if(flag & BGP_ATTR_FLAG_EXTLEN) { unknown->raw[2] = (len & 0xFF00) >> 8; unknown->raw[3] = len & 0xFF; mstream_get(s, unknown->raw + 4, unknown->real_len); } else { unknown->raw[2] = len; mstream_get(s, unknown->raw + 3, unknown->real_len); } break; }