📄 bgp_attr.c
字号:
/* BGP attributes management routines. Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro This file is part of GNU Zebra. GNU Zebra is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Zebra is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Zebra; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <zebra.h>#include "linklist.h"#include "prefix.h"#include "memory.h"#include "vector.h"#include "vty.h"#include "stream.h"#include "log.h"#include "hash.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_attr.h"#include "bgpd/bgp_route.h"#include "bgpd/bgp_aspath.h"#include "bgpd/bgp_community.h"#include "bgpd/bgp_debug.h"#include "bgpd/bgp_packet.h"#include "bgpd/bgp_ecommunity.h"/* Attribute strings for logging. */struct message attr_str [] = { { BGP_ATTR_ORIGIN, "ORIGIN" }, { BGP_ATTR_AS_PATH, "AS_PATH" }, { BGP_ATTR_NEXT_HOP, "NEXT_HOP" }, { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" }, { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" }, { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" }, { BGP_ATTR_AGGREGATOR, "AGGREGATOR" }, { BGP_ATTR_COMMUNITIES, "COMMUNITY" }, { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" }, { BGP_ATTR_CLUSTER_LIST, "CLUSTERLIST" }, { BGP_ATTR_DPA, "DPA" }, { BGP_ATTR_ADVERTISER, "ADVERTISER"} , { BGP_ATTR_RCID_PATH, "RCID_PATH" }, { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" }, { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" }, { 0, NULL } };struct hash *cluster_hash;void *cluster_hash_alloc (struct cluster_list *val){ struct cluster_list *cluster; cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list)); cluster->length = val->length; if (cluster->length) { cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length); memcpy (cluster->list, val->list, val->length); } else cluster->list = NULL; cluster->refcnt = 0; return cluster;}/* Cluster list related functions. */struct cluster_list *cluster_parse (caddr_t pnt, int length){ struct cluster_list tmp; struct cluster_list *cluster; tmp.length = length; tmp.list = (struct in_addr *) pnt; cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc); cluster->refcnt++; return cluster;}intcluster_loop_check (struct cluster_list *cluster, struct in_addr originator){ int i; for (i = 0; i < cluster->length / 4; i++) if (cluster->list[i].s_addr == originator.s_addr) return 1; return 0;}unsigned intcluster_hash_key_make (struct cluster_list *cluster){ unsigned int key = 0; int length; caddr_t pnt; length = cluster->length; pnt = (caddr_t) cluster->list; while (length) key += pnt[--length]; return key;}intcluster_hash_cmp (struct cluster_list *cluster1, struct cluster_list *cluster2){ if (cluster1->length == cluster2->length && memcmp (cluster1->list, cluster2->list, cluster1->length) == 0) return 1; return 0;}voidcluster_free (struct cluster_list *cluster){ if (cluster->list) XFREE (MTYPE_CLUSTER_VAL, cluster->list); XFREE (MTYPE_CLUSTER, cluster);}struct cluster_list *cluster_dup (struct cluster_list *cluster){ struct cluster_list *new; new = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list)); memset (new, 0, sizeof (struct cluster_list)); new->length = cluster->length; if (cluster->length) { new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length); memcpy (new->list, cluster->list, cluster->length); } else new->list = NULL; return new;}struct cluster_list *cluster_intern (struct cluster_list *cluster){ struct cluster_list *find; find = hash_get (cluster_hash, cluster, cluster_hash_alloc); find->refcnt++; return find;}voidcluster_unintern (struct cluster_list *cluster){ struct cluster_list *ret; if (cluster->refcnt) cluster->refcnt--; if (cluster->refcnt == 0) { ret = hash_release (cluster_hash, cluster); cluster_free (cluster); }}voidcluster_init (){ cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);}/* Unknown transit attribute. */struct hash *transit_hash;voidtransit_free (struct transit *transit){ if (transit->val) XFREE (MTYPE_TRANSIT_VAL, transit->val); XFREE (MTYPE_TRANSIT, transit);}void *transit_hash_alloc (struct transit *transit){ /* Transit structure is already allocated. */ return transit;}struct transit *transit_intern (struct transit *transit){ struct transit *find; find = hash_get (transit_hash, transit, transit_hash_alloc); if (find != transit) transit_free (transit); find->refcnt++; return find;}voidtransit_unintern (struct transit *transit){ struct transit *ret; if (transit->refcnt) transit->refcnt--; if (transit->refcnt == 0) { ret = hash_release (transit_hash, transit); transit_free (transit); }}unsigned inttransit_hash_key_make (struct transit *transit){ unsigned int key = 0; int length; caddr_t pnt; length = transit->length; pnt = (caddr_t) transit->val; while (length) key += pnt[--length]; return key;}inttransit_hash_cmp (struct transit *transit1, struct transit *transit2){ if (transit1->length == transit2->length && memcmp (transit1->val, transit2->val, transit1->length) == 0) return 1; return 0;}voidtransit_init (){ transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp);}/* Attribute hash routines. */struct hash *attrhash;unsigned intattrhash_key_make (struct attr *attr){ unsigned int key = 0; key += attr->origin; key += attr->nexthop.s_addr; key += attr->med; key += attr->local_pref; key += attr->aggregator_as; key += attr->aggregator_addr.s_addr; key += attr->weight; key += attr->mp_nexthop_global_in.s_addr; if (attr->aspath) key += aspath_key_make (attr->aspath); if (attr->community) key += community_hash_make (attr->community); if (attr->ecommunity) key += ecommunity_hash_make (attr->ecommunity); if (attr->cluster) key += cluster_hash_key_make (attr->cluster); if (attr->transit) key += transit_hash_key_make (attr->transit);#ifdef HAVE_IPV6 { int i; key += attr->mp_nexthop_len; for (i = 0; i < 16; i++) key += attr->mp_nexthop_global.s6_addr[i]; for (i = 0; i < 16; i++) key += attr->mp_nexthop_local.s6_addr[i]; }#endif /* HAVE_IPV6 */ return key;}intattrhash_cmp (struct attr *attr1, struct attr *attr2){ if (attr1->flag == attr2->flag && attr1->origin == attr2->origin && attr1->nexthop.s_addr == attr2->nexthop.s_addr && attr1->med == attr2->med && attr1->local_pref == attr2->local_pref && attr1->aggregator_as == attr2->aggregator_as && attr1->aggregator_addr.s_addr == attr2->aggregator_addr.s_addr && attr1->weight == attr2->weight#ifdef HAVE_IPV6 && attr1->mp_nexthop_len == attr2->mp_nexthop_len && IPV6_ADDR_SAME (&attr1->mp_nexthop_global, &attr2->mp_nexthop_global) && IPV6_ADDR_SAME (&attr1->mp_nexthop_local, &attr2->mp_nexthop_local)#endif /* HAVE_IPV6 */ && IPV4_ADDR_SAME (&attr1->mp_nexthop_global_in, &attr2->mp_nexthop_global_in) && attr1->aspath == attr2->aspath && attr1->community == attr2->community && attr1->ecommunity == attr2->ecommunity && attr1->cluster == attr2->cluster && attr1->transit == attr2->transit) return 1; else return 0;}voidattrhash_init (){ attrhash = hash_create (attrhash_key_make, attrhash_cmp);}voidattr_show_all_iterator (struct hash_backet *backet, struct vty *vty){ struct attr *attr = backet->data; vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt, inet_ntoa (attr->nexthop), VTY_NEWLINE);}voidattr_show_all (struct vty *vty){ hash_iterate (attrhash, (void (*)(struct hash_backet *, void *)) attr_show_all_iterator, vty);}void *bgp_attr_hash_alloc (struct attr *val){ struct attr *attr; attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr)); *attr = *val; attr->refcnt = 0; return attr;}/* Internet argument attribute. */struct attr *bgp_attr_intern (struct attr *attr){ struct attr *find; /* Intern referenced strucutre. */ if (attr->aspath) { if (! attr->aspath->refcnt) attr->aspath = aspath_intern (attr->aspath); else attr->aspath->refcnt++; } if (attr->community) { if (! attr->community->refcnt) attr->community = community_intern (attr->community); else attr->community->refcnt++; } if (attr->ecommunity) { if (! attr->ecommunity->refcnt) attr->ecommunity = ecommunity_intern (attr->ecommunity); else attr->ecommunity->refcnt++; } if (attr->cluster) { if (! attr->cluster->refcnt) attr->cluster = cluster_intern (attr->cluster); else attr->cluster->refcnt++; } if (attr->transit) { if (! attr->transit->refcnt) attr->transit = transit_intern (attr->transit); else attr->transit->refcnt++; } find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc); find->refcnt++; return find;}/* Make network statement's attribute. */struct attr *bgp_attr_default_set (struct attr *attr, u_char origin){ memset (attr, 0, sizeof (struct attr)); attr->origin = origin; attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); attr->aspath = aspath_empty (); attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); attr->weight = 32768; attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);#ifdef HAVE_IPV6 attr->mp_nexthop_len = 16;#endif return attr;}/* Make network statement's attribute. */struct attr *bgp_attr_default_intern (u_char origin){ struct attr attr; struct attr *new; memset (&attr, 0, sizeof (struct attr)); attr.origin = origin; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); attr.aspath = aspath_empty (); attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); attr.weight = 32768; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -