Annotation of embedaddon/quagga/bgpd/bgp_advertise.c, revision 1.1
1.1 ! misho 1: /* BGP advertisement and adjacency
! 2: Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
! 3:
! 4: This file is part of GNU Zebra.
! 5:
! 6: GNU Zebra is free software; you can redistribute it and/or modify it
! 7: under the terms of the GNU General Public License as published by the
! 8: Free Software Foundation; either version 2, or (at your option) any
! 9: later version.
! 10:
! 11: GNU Zebra is distributed in the hope that it will be useful, but
! 12: WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 14: General Public License for more details.
! 15:
! 16: You should have received a copy of the GNU General Public License
! 17: along with GNU Zebra; see the file COPYING. If not, write to the Free
! 18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 19: 02111-1307, USA. */
! 20:
! 21: #include <zebra.h>
! 22:
! 23: #include "command.h"
! 24: #include "memory.h"
! 25: #include "prefix.h"
! 26: #include "hash.h"
! 27: #include "thread.h"
! 28:
! 29: #include "bgpd/bgpd.h"
! 30: #include "bgpd/bgp_table.h"
! 31: #include "bgpd/bgp_route.h"
! 32: #include "bgpd/bgp_advertise.h"
! 33: #include "bgpd/bgp_attr.h"
! 34: #include "bgpd/bgp_aspath.h"
! 35: #include "bgpd/bgp_packet.h"
! 36: #include "bgpd/bgp_fsm.h"
! 37: #include "bgpd/bgp_mplsvpn.h"
! 38:
! 39: /* BGP advertise attribute is used for pack same attribute update into
! 40: one packet. To do that we maintain attribute hash in struct
! 41: peer. */
! 42: static struct bgp_advertise_attr *
! 43: baa_new (void)
! 44: {
! 45: return (struct bgp_advertise_attr *)
! 46: XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr));
! 47: }
! 48:
! 49: static void
! 50: baa_free (struct bgp_advertise_attr *baa)
! 51: {
! 52: XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa);
! 53: }
! 54:
! 55: static void *
! 56: baa_hash_alloc (void *p)
! 57: {
! 58: struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p;
! 59: struct bgp_advertise_attr *baa;
! 60:
! 61: baa = baa_new ();
! 62: baa->attr = ref->attr;
! 63: return baa;
! 64: }
! 65:
! 66: static unsigned int
! 67: baa_hash_key (void *p)
! 68: {
! 69: struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p;
! 70:
! 71: return attrhash_key_make (baa->attr);
! 72: }
! 73:
! 74: static int
! 75: baa_hash_cmp (const void *p1, const void *p2)
! 76: {
! 77: const struct bgp_advertise_attr * baa1 = p1;
! 78: const struct bgp_advertise_attr * baa2 = p2;
! 79:
! 80: return attrhash_cmp (baa1->attr, baa2->attr);
! 81: }
! 82:
! 83: /* BGP update and withdraw information is stored in BGP advertise
! 84: structure. This structure is referred from BGP adjacency
! 85: information. */
! 86: static struct bgp_advertise *
! 87: bgp_advertise_new (void)
! 88: {
! 89: return (struct bgp_advertise *)
! 90: XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
! 91: }
! 92:
! 93: static void
! 94: bgp_advertise_free (struct bgp_advertise *adv)
! 95: {
! 96: if (adv->binfo)
! 97: bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */
! 98: XFREE (MTYPE_BGP_ADVERTISE, adv);
! 99: }
! 100:
! 101: static void
! 102: bgp_advertise_add (struct bgp_advertise_attr *baa,
! 103: struct bgp_advertise *adv)
! 104: {
! 105: adv->next = baa->adv;
! 106: if (baa->adv)
! 107: baa->adv->prev = adv;
! 108: baa->adv = adv;
! 109: }
! 110:
! 111: static void
! 112: bgp_advertise_delete (struct bgp_advertise_attr *baa,
! 113: struct bgp_advertise *adv)
! 114: {
! 115: if (adv->next)
! 116: adv->next->prev = adv->prev;
! 117: if (adv->prev)
! 118: adv->prev->next = adv->next;
! 119: else
! 120: baa->adv = adv->next;
! 121: }
! 122:
! 123: static struct bgp_advertise_attr *
! 124: bgp_advertise_intern (struct hash *hash, struct attr *attr)
! 125: {
! 126: struct bgp_advertise_attr ref;
! 127: struct bgp_advertise_attr *baa;
! 128:
! 129: ref.attr = bgp_attr_intern (attr);
! 130: baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc);
! 131: baa->refcnt++;
! 132:
! 133: return baa;
! 134: }
! 135:
! 136: static void
! 137: bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
! 138: {
! 139: if (baa->refcnt)
! 140: baa->refcnt--;
! 141:
! 142: if (baa->refcnt && baa->attr)
! 143: bgp_attr_unintern (&baa->attr);
! 144: else
! 145: {
! 146: if (baa->attr)
! 147: {
! 148: hash_release (hash, baa);
! 149: bgp_attr_unintern (&baa->attr);
! 150: }
! 151: baa_free (baa);
! 152: }
! 153: }
! 154:
! 155: /* BGP adjacency keeps minimal advertisement information. */
! 156: static void
! 157: bgp_adj_out_free (struct bgp_adj_out *adj)
! 158: {
! 159: peer_unlock (adj->peer); /* adj_out peer reference */
! 160: XFREE (MTYPE_BGP_ADJ_OUT, adj);
! 161: }
! 162:
! 163: int
! 164: bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
! 165: afi_t afi, safi_t safi, struct bgp_node *rn)
! 166: {
! 167: struct bgp_adj_out *adj;
! 168:
! 169: for (adj = rn->adj_out; adj; adj = adj->next)
! 170: if (adj->peer == peer)
! 171: break;
! 172:
! 173: if (! adj)
! 174: return 0;
! 175:
! 176: return (adj->adv
! 177: ? (adj->adv->baa ? 1 : 0)
! 178: : (adj->attr ? 1 : 0));
! 179: }
! 180:
! 181: struct bgp_advertise *
! 182: bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj,
! 183: afi_t afi, safi_t safi)
! 184: {
! 185: struct bgp_advertise *adv;
! 186: struct bgp_advertise_attr *baa;
! 187: struct bgp_advertise *next;
! 188:
! 189: adv = adj->adv;
! 190: baa = adv->baa;
! 191: next = NULL;
! 192:
! 193: if (baa)
! 194: {
! 195: /* Unlink myself from advertise attribute FIFO. */
! 196: bgp_advertise_delete (baa, adv);
! 197:
! 198: /* Fetch next advertise candidate. */
! 199: next = baa->adv;
! 200:
! 201: /* Unintern BGP advertise attribute. */
! 202: bgp_advertise_unintern (peer->hash[afi][safi], baa);
! 203: }
! 204:
! 205: /* Unlink myself from advertisement FIFO. */
! 206: FIFO_DEL (adv);
! 207:
! 208: /* Free memory. */
! 209: bgp_advertise_free (adj->adv);
! 210: adj->adv = NULL;
! 211:
! 212: return next;
! 213: }
! 214:
! 215: void
! 216: bgp_adj_out_set (struct bgp_node *rn, struct peer *peer, struct prefix *p,
! 217: struct attr *attr, afi_t afi, safi_t safi,
! 218: struct bgp_info *binfo)
! 219: {
! 220: struct bgp_adj_out *adj = NULL;
! 221: struct bgp_advertise *adv;
! 222:
! 223: if (DISABLE_BGP_ANNOUNCE)
! 224: return;
! 225:
! 226: /* Look for adjacency information. */
! 227: if (rn)
! 228: {
! 229: for (adj = rn->adj_out; adj; adj = adj->next)
! 230: if (adj->peer == peer)
! 231: break;
! 232: }
! 233:
! 234: if (! adj)
! 235: {
! 236: adj = XCALLOC (MTYPE_BGP_ADJ_OUT, sizeof (struct bgp_adj_out));
! 237: adj->peer = peer_lock (peer); /* adj_out peer reference */
! 238:
! 239: if (rn)
! 240: {
! 241: BGP_ADJ_OUT_ADD (rn, adj);
! 242: bgp_lock_node (rn);
! 243: }
! 244: }
! 245:
! 246: if (adj->adv)
! 247: bgp_advertise_clean (peer, adj, afi, safi);
! 248:
! 249: adj->adv = bgp_advertise_new ();
! 250:
! 251: adv = adj->adv;
! 252: adv->rn = rn;
! 253:
! 254: assert (adv->binfo == NULL);
! 255: adv->binfo = bgp_info_lock (binfo); /* bgp_info adj_out reference */
! 256:
! 257: if (attr)
! 258: adv->baa = bgp_advertise_intern (peer->hash[afi][safi], attr);
! 259: else
! 260: adv->baa = baa_new ();
! 261: adv->adj = adj;
! 262:
! 263: /* Add new advertisement to advertisement attribute list. */
! 264: bgp_advertise_add (adv->baa, adv);
! 265:
! 266: FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo);
! 267: }
! 268:
! 269: void
! 270: bgp_adj_out_unset (struct bgp_node *rn, struct peer *peer, struct prefix *p,
! 271: afi_t afi, safi_t safi)
! 272: {
! 273: struct bgp_adj_out *adj;
! 274: struct bgp_advertise *adv;
! 275:
! 276: if (DISABLE_BGP_ANNOUNCE)
! 277: return;
! 278:
! 279: /* Lookup existing adjacency, if it is not there return immediately. */
! 280: for (adj = rn->adj_out; adj; adj = adj->next)
! 281: if (adj->peer == peer)
! 282: break;
! 283:
! 284: if (! adj)
! 285: return;
! 286:
! 287: /* Clearn up previous advertisement. */
! 288: if (adj->adv)
! 289: bgp_advertise_clean (peer, adj, afi, safi);
! 290:
! 291: if (adj->attr)
! 292: {
! 293: /* We need advertisement structure. */
! 294: adj->adv = bgp_advertise_new ();
! 295: adv = adj->adv;
! 296: adv->rn = rn;
! 297: adv->adj = adj;
! 298:
! 299: /* Add to synchronization entry for withdraw announcement. */
! 300: FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo);
! 301:
! 302: /* Schedule packet write. */
! 303: BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
! 304: }
! 305: else
! 306: {
! 307: /* Remove myself from adjacency. */
! 308: BGP_ADJ_OUT_DEL (rn, adj);
! 309:
! 310: /* Free allocated information. */
! 311: bgp_adj_out_free (adj);
! 312:
! 313: bgp_unlock_node (rn);
! 314: }
! 315: }
! 316:
! 317: void
! 318: bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj,
! 319: struct peer *peer, afi_t afi, safi_t safi)
! 320: {
! 321: if (adj->attr)
! 322: bgp_attr_unintern (&adj->attr);
! 323:
! 324: if (adj->adv)
! 325: bgp_advertise_clean (peer, adj, afi, safi);
! 326:
! 327: BGP_ADJ_OUT_DEL (rn, adj);
! 328: bgp_adj_out_free (adj);
! 329: }
! 330:
! 331: void
! 332: bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
! 333: {
! 334: struct bgp_adj_in *adj;
! 335:
! 336: for (adj = rn->adj_in; adj; adj = adj->next)
! 337: {
! 338: if (adj->peer == peer)
! 339: {
! 340: if (adj->attr != attr)
! 341: {
! 342: bgp_attr_unintern (&adj->attr);
! 343: adj->attr = bgp_attr_intern (attr);
! 344: }
! 345: return;
! 346: }
! 347: }
! 348: adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
! 349: adj->peer = peer_lock (peer); /* adj_in peer reference */
! 350: adj->attr = bgp_attr_intern (attr);
! 351: BGP_ADJ_IN_ADD (rn, adj);
! 352: bgp_lock_node (rn);
! 353: }
! 354:
! 355: void
! 356: bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
! 357: {
! 358: bgp_attr_unintern (&bai->attr);
! 359: BGP_ADJ_IN_DEL (rn, bai);
! 360: peer_unlock (bai->peer); /* adj_in peer reference */
! 361: XFREE (MTYPE_BGP_ADJ_IN, bai);
! 362: }
! 363:
! 364: void
! 365: bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer)
! 366: {
! 367: struct bgp_adj_in *adj;
! 368:
! 369: for (adj = rn->adj_in; adj; adj = adj->next)
! 370: if (adj->peer == peer)
! 371: break;
! 372:
! 373: if (! adj)
! 374: return;
! 375:
! 376: bgp_adj_in_remove (rn, adj);
! 377: bgp_unlock_node (rn);
! 378: }
! 379:
! 380: void
! 381: bgp_sync_init (struct peer *peer)
! 382: {
! 383: afi_t afi;
! 384: safi_t safi;
! 385: struct bgp_synchronize *sync;
! 386:
! 387: for (afi = AFI_IP; afi < AFI_MAX; afi++)
! 388: for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
! 389: {
! 390: sync = XCALLOC (MTYPE_BGP_SYNCHRONISE,
! 391: sizeof (struct bgp_synchronize));
! 392: FIFO_INIT (&sync->update);
! 393: FIFO_INIT (&sync->withdraw);
! 394: FIFO_INIT (&sync->withdraw_low);
! 395: peer->sync[afi][safi] = sync;
! 396: peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp);
! 397: }
! 398: }
! 399:
! 400: void
! 401: bgp_sync_delete (struct peer *peer)
! 402: {
! 403: afi_t afi;
! 404: safi_t safi;
! 405:
! 406: for (afi = AFI_IP; afi < AFI_MAX; afi++)
! 407: for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
! 408: {
! 409: if (peer->sync[afi][safi])
! 410: XFREE (MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
! 411: peer->sync[afi][safi] = NULL;
! 412:
! 413: if (peer->hash[afi][safi])
! 414: hash_free (peer->hash[afi][safi]);
! 415: peer->hash[afi][safi] = NULL;
! 416: }
! 417: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>