/* empty-prepend testing */ static void empty_prepend_test (struct test_segment *t) { struct aspath *asp1, *asp2, *ascratch; printf ("empty prepend %s: %s\n", t->name, t->desc); asp1 = make_aspath (t->asdata, t->len, 0); asp2 = aspath_empty (); ascratch = aspath_dup (asp2); aspath_unintern (asp2); asp2 = aspath_prepend (asp1, ascratch); printf ("aspath: %s\n", aspath_print (asp2)); if (!validate (asp2, &t->sp)) printf (OK "\n"); else printf (FAILED "!\n"); printf ("\n"); aspath_unintern (asp1); aspath_free (asp2); }
/* prepend testing */ static void prepend_test (struct tests *t) { struct aspath *asp1, *asp2, *ascratch; printf ("prepend %s: %s\n", t->test1->name, t->test1->desc); printf ("to %s: %s\n", t->test2->name, t->test2->desc); asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); ascratch = aspath_dup (asp2); aspath_unintern (asp2); asp2 = aspath_prepend (asp1, ascratch); printf ("aspath: %s\n", aspath_print (asp2)); if (!validate (asp2, &t->sp)) printf ("%s\n", OK); else printf ("%s!\n", FAILED); printf ("\n"); aspath_unintern (asp1); aspath_free (asp2); }
static int attr_parse (struct stream *s, u_int16_t len) { u_int flag; u_int type; u_int16_t length; u_int16_t lim; lim = s->getp + len; printf ("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim); while (s->getp < lim) { flag = stream_getc (s); type = stream_getc (s); if (flag & BGP_ATTR_FLAG_EXTLEN) length = stream_getw (s); else length = stream_getc (s); printf ("FLAG: %d\n", flag); printf ("TYPE: %d\n", type); printf ("Len: %d\n", length); switch (type) { case BGP_ATTR_ORIGIN: { u_char origin; origin = stream_getc (s); printf ("ORIGIN: %d\n", origin); } break; case BGP_ATTR_AS_PATH: { struct aspath *aspath; aspath = aspath_parse (s, length, 1); printf ("ASPATH: %s\n", aspath->str); aspath_free(aspath); } break; case BGP_ATTR_NEXT_HOP: { struct in_addr nexthop; nexthop.s_addr = stream_get_ipv4 (s); printf ("NEXTHOP: %s\n", inet_ntoa (nexthop)); } break; default: stream_getw_from (s, length); break; } } return 0; }
static void empty_get_test () { struct aspath *as = aspath_empty_get (); struct test_spec sp = { "", "", 0, 0, 0, 0, 0, 0 }; printf ("empty_get_test, as: %s\n",aspath_print (as)); if (!validate (as, &sp)) printf ("%s\n", OK); else printf ("%s!\n", FAILED); printf ("\n"); aspath_free (as); }
/* as2+as4 reconciliation testing */ static void as4_reconcile_test (struct tests *t) { struct aspath *asp1, *asp2, *ascratch; printf ("reconciling %s:\n %s\n", t->test1->name, t->test1->desc); printf ("with %s:\n %s\n", t->test2->name, t->test2->desc); asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); ascratch = aspath_reconcile_as4 (asp1, asp2); if (!validate (ascratch, &t->sp)) printf (OK "\n"); else printf (FAILED "!\n"); printf ("\n"); aspath_unintern (asp1); aspath_unintern (asp2); aspath_free (ascratch); }
/* aggregation testing */ static void aggregate_test (struct tests *t) { struct aspath *asp1, *asp2, *ascratch; printf ("aggregate %s: %s\n", t->test1->name, t->test1->desc); printf ("with %s: %s\n", t->test2->name, t->test2->desc); asp1 = make_aspath (t->test1->asdata, t->test1->len, 0); asp2 = make_aspath (t->test2->asdata, t->test2->len, 0); ascratch = aspath_aggregate (asp1, asp2); if (!validate (ascratch, &t->sp)) printf (OK "\n"); else printf (FAILED "!\n"); printf ("\n"); aspath_unintern (asp1); aspath_unintern (asp2); aspath_free (ascratch); /* aspath_unintern (ascratch);*/ }
/******************************************************************************* 函数名称 : 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); } }
/* validate the given aspath */ static int validate (struct aspath *as, const struct test_spec *sp) { size_t bytes, bytes4; int fails = 0; const u_char *out; static struct stream *s; struct aspath *asinout, *asconfeddel, *asstr, *as4; out = aspath_snmp_pathseg (as, &bytes); asinout = make_aspath (out, bytes, 0); /* Excercise AS4 parsing a bit, with a dogfood test */ if (!s) s = stream_new (4096); bytes4 = aspath_put (s, as, 1); as4 = make_aspath (STREAM_DATA(s), bytes4, 1); asstr = aspath_str2aspath (sp->shouldbe); asconfeddel = aspath_delete_confed_seq (aspath_dup (asinout)); printf ("got: %s\n", aspath_print(as)); /* the parsed path should match the specified 'shouldbe' string. * We should pass the "eat our own dog food" test, be able to output * this path and then input it again. Ie the path resulting from: * * aspath_parse(aspath_put(as)) * * should: * * - also match the specified 'shouldbe' value * - hash to same value as original path * - have same hops and confed counts as original, and as the * the specified counts * * aspath_str2aspath() and shouldbe should match * * We do the same for: * * aspath_parse(aspath_put(as,USE32BIT)) * * Confederation related tests: * - aspath_delete_confed_seq(aspath) should match shouldbe_confed * - aspath_delete_confed_seq should be idempotent. */ if (strcmp(aspath_print (as), sp->shouldbe) /* hash validation */ || (aspath_key_make (as) != aspath_key_make (asinout)) /* by string */ || strcmp(aspath_print (asinout), sp->shouldbe) /* By 4-byte parsing */ || strcmp(aspath_print (as4), sp->shouldbe) /* by various path counts */ || (aspath_count_hops (as) != sp->hops) || (aspath_count_confeds (as) != sp->confeds) || (aspath_count_hops (asinout) != sp->hops) || (aspath_count_confeds (asinout) != sp->confeds)) { failed++; fails++; printf ("shouldbe:\n%s\n", sp->shouldbe); printf ("as4:\n%s\n", aspath_print (as4)); printf ("hash keys: in: %d out->in: %d\n", aspath_key_make (as), aspath_key_make (asinout)); printf ("hops: %d, counted %d %d\n", sp->hops, aspath_count_hops (as), aspath_count_hops (asinout) ); printf ("confeds: %d, counted %d %d\n", sp->confeds, aspath_count_confeds (as), aspath_count_confeds (asinout)); printf ("out->in:\n%s\nbytes: ", aspath_print(asinout)); printbytes (out, bytes); } /* basic confed related tests */ if ((aspath_print (asconfeddel) == NULL && sp->shouldbe_delete_confed != NULL) || (aspath_print (asconfeddel) != NULL && sp->shouldbe_delete_confed == NULL) || strcmp(aspath_print (asconfeddel), sp->shouldbe_delete_confed) /* delete_confed_seq should be idempotent */ || (aspath_key_make (asconfeddel) != aspath_key_make (aspath_delete_confed_seq (asconfeddel)))) { failed++; fails++; printf ("confed_del: %s\n", aspath_print (asconfeddel)); printf ("should be: %s\n", sp->shouldbe_delete_confed); } /* aspath_str2aspath test */ if ((aspath_print (asstr) == NULL && sp->shouldbe != NULL) || (aspath_print (asstr) != NULL && sp->shouldbe == NULL) || strcmp(aspath_print (asstr), sp->shouldbe)) { failed++; fails++; printf ("asstr: %s\n", aspath_print (asstr)); } /* loop, private and first as checks */ if ((sp->does_loop && aspath_loop_check (as, sp->does_loop) == 0) || (sp->doesnt_loop && aspath_loop_check (as, sp->doesnt_loop) != 0) || (aspath_private_as_check (as) != sp->private_as) || (aspath_firstas_check (as,sp->first) && sp->first == 0)) { failed++; fails++; printf ("firstas: %d, got %d\n", sp->first, aspath_firstas_check (as,sp->first)); printf ("loop does: %d %d, doesnt: %d %d\n", sp->does_loop, aspath_loop_check (as, sp->does_loop), sp->doesnt_loop, aspath_loop_check (as, sp->doesnt_loop)); printf ("private check: %d %d\n", sp->private_as, aspath_private_as_check (as)); } aspath_unintern (asinout); aspath_unintern (as4); aspath_free (asconfeddel); aspath_free (asstr); stream_reset (s); return fails; }