cpudb.c (22169B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: cpudb.c 8 * Purpose: CPU database; 9 * Requires: 10 * 11 * See the document cpu_database.txt for more information. 12 * 13 * The sysid is an application specific number between 0 and number 14 * of CPUs permitted. It is independent of the hard index used 15 * by cpudb. 16 */ 17 18 #include <assert.h> 19 20 #include <sal/core/sync.h> 21 #include <sal/core/libc.h> 22 #include <shared/alloc.h> 23 24 #include <bcm/types.h> 25 #include <bcm/error.h> 26 27 #include <appl/cpudb/cpudb.h> 28 29 #define CPUDB_CHECK(db_ref, rv) if (!DB_REF_VALID(db_ref)) return (rv) 30 #define CPUDB_MAGIC 0xfeedface 31 #define DB_REF_VALID(db_ref) \ 32 (((db_ref) != NULL) && ((db_ref)->magic == CPUDB_MAGIC)) 33 #define CPUDB_SET_MAGIC(db_ref) (db_ref)->magic = CPUDB_MAGIC 34 #define CPUDB_CLEAR_MAGIC(db_ref) (db_ref)->magic = 0 35 36 /* Declare broadcast and neighbor keys */ 37 CPUDB_BCAST_KEY_DECLARATION; 38 CPUDB_NEIGHBOR_KEY_DECLARATION; 39 40 static sal_mutex_t cpudb_lock; 41 #define _CPUDB_LOCK sal_mutex_take(cpudb_lock, sal_mutex_FOREVER) 42 #define _CPUDB_UNLOCK sal_mutex_give(cpudb_lock) 43 #define INIT_DONE (cpudb_lock != NULL) 44 45 STATIC int 46 _cpudb_init(void) 47 { 48 if (cpudb_lock == NULL) { 49 cpudb_lock = sal_mutex_create("cpudb-int-lock"); 50 if (cpudb_lock == NULL) { 51 return BCM_E_MEMORY; 52 } 53 } 54 55 return BCM_E_NONE; 56 } 57 58 STATIC cpudb_entry_t *_cpudb_entry_create(cpudb_t *db_ref, 59 const cpudb_key_t key); 60 61 /**************************************************************** 62 * 63 * DB selection functions 64 * cpudb_create Create a DB 65 * cpudb_destroy De-init a DB 66 * cpudb_valid Check if DB reference is valid 67 * cpudb_clear Remove all info from a DB 68 */ 69 70 71 /* 72 * Function: 73 * cpudb_create 74 * Purpose: 75 * Create a database 76 * Parameters: 77 * Returns: 78 * Small integer reference >= 0 if successful; used in cpudb calls. 79 * BCM_E_XXX < 0 otherwise. 80 * Notes: 81 */ 82 83 cpudb_ref_t 84 cpudb_create(void) 85 { 86 cpudb_t *db; 87 88 if (!INIT_DONE) { 89 if (_cpudb_init() < 0) { 90 return NULL; 91 } 92 } 93 94 db = sal_alloc(sizeof(cpudb_t), "cpudb_create"); 95 if (db == NULL) { 96 return NULL; 97 } 98 99 sal_memset(db, 0, sizeof(cpudb_t)); 100 CPUDB_SET_MAGIC(db); 101 db->old_db = CPUDB_REF_NULL; 102 103 return db; 104 } 105 106 107 STATIC int 108 _cpudb_clear(cpudb_ref_t db_ref, int keep_local) 109 { 110 int i; 111 cpudb_entry_t *entry, *next_entry; 112 cpudb_entry_t save_local_entry; 113 int saved = FALSE; 114 115 if (keep_local) { 116 if (db_ref->local_entry != NULL) { 117 sal_memcpy(&save_local_entry, db_ref->local_entry, 118 sizeof(cpudb_entry_t)); 119 saved = TRUE; 120 } 121 } 122 123 for (entry = db_ref->entries; entry != NULL; entry = next_entry) { 124 next_entry = entry->next; 125 sal_free(entry); 126 } 127 128 db_ref->entries = NULL; 129 db_ref->num_cpus = 0; 130 131 /* Clear key hashes */ 132 for (i = 0; i < CPUDB_HASH_ENTRY_COUNT; i++) { 133 db_ref->key_hash[i] = NULL; 134 } 135 136 db_ref->master_entry = NULL; 137 138 if (saved) { 139 entry = _cpudb_entry_create(db_ref, save_local_entry.base.key); 140 if (entry == NULL) { 141 return BCM_E_FAIL; 142 } 143 sal_memcpy(&entry->base, &save_local_entry.base, 144 sizeof(cpudb_base_t)); 145 entry->flags = CPUDB_F_IS_LOCAL | CPUDB_F_BASE_INIT_DONE; 146 db_ref->local_entry = entry; 147 /* Clear the stack info for the local entry */ 148 for (i = 0; i < entry->base.num_stk_ports; i++) { 149 /* Clear all flags except no link and ETH flag */ 150 entry->sp_info[i].flags = 151 save_local_entry.sp_info[i].flags & 152 (CPUDB_SPF_NO_LINK|CPUDB_SPF_ETHERNET); 153 } 154 } 155 156 return BCM_E_NONE; 157 } 158 159 160 /* 161 * Function: 162 * cpudb_clear 163 * Purpose: 164 * Clear (initialized) the given DB. 165 * Parameters: 166 * db_ref - which DB to clear 167 * keep_local - Boolean indicating if local entry should be kept 168 * Returns: 169 * BCM_E_XXX 170 * Notes: 171 * Only the base info and user_cookie of the local entry is kept. 172 * The flags are cleared except for "is_local" 173 */ 174 175 int 176 cpudb_clear(cpudb_ref_t db_ref, int keep_local) 177 { 178 int rv; 179 180 CPUDB_CHECK(db_ref, BCM_E_PARAM); 181 _CPUDB_LOCK; 182 rv = _cpudb_clear(db_ref, keep_local); 183 _CPUDB_UNLOCK; 184 185 return rv; 186 } 187 188 189 /* 190 * Function: 191 * cpudb_destroy 192 * Purpose: 193 * De-init a database 194 * Parameters: 195 * db_ref - Reference to DB to destroy 196 * Returns: 197 * BCM_E_XXX 198 * Notes: 199 * There should be no calls pending on the db_lock of this DB. 200 * Will not destroy db_ref->old_db even if non-NULL. 201 */ 202 203 int 204 cpudb_destroy(cpudb_ref_t db_ref) 205 { 206 int rv; 207 208 CPUDB_CHECK(db_ref, BCM_E_PARAM); 209 _CPUDB_LOCK; 210 CPUDB_CLEAR_MAGIC(db_ref); 211 212 rv = _cpudb_clear(db_ref, FALSE); 213 if (rv == BCM_E_NONE) { 214 sal_free(db_ref); 215 } else { /* Shouldn't happen with keep_local == FALSE */ 216 assert(!"CPUDB failed to clear DB"); 217 } 218 _CPUDB_UNLOCK; 219 220 return rv; 221 } 222 223 224 /* 225 * Function: 226 * cpudb_valid 227 * Purpose: 228 * Is a CPU DB reference currently valid? 229 * Parameters: 230 * db_ref - The database reference to check 231 * Returns: 232 * Boolean: True means currently exists 233 */ 234 235 int 236 cpudb_valid(cpudb_ref_t db_ref) 237 { 238 return DB_REF_VALID(db_ref); 239 } 240 241 242 /**************************************************************** 243 * 244 * Create functions 245 * cpudb_entry_create Add an entry 246 * cpudb_entry_count_get How many CPU entries in DB 247 * 248 * Set functions 249 * cpudb_sysid_set Set system id by key 250 * 251 * Lookup functions; see also macros in cpudb.h 252 * cpudb_mac_lookup Get entry pointer by MAC 253 * cpudb_sysid_lookup Get entry pointer by system id 254 * 255 * Remove functions 256 * cpudb_entry_remove Remove entry with given key 257 */ 258 259 STATIC void _cpudb_unlink_entry(cpudb_ref_t db_ref, 260 cpudb_entry_t *entry); 261 262 /* 263 * Function: 264 * cpudb_entry_create 265 * Purpose: 266 * Create an entry for the given key with locking 267 * Parameters: 268 * db_ref - The database reference 269 * key - The key to identify new entry 270 * Returns: 271 * Pointer to entry created 272 * Notes: 273 * Returns pointer to the entry or NULL if fails 274 */ 275 276 cpudb_entry_t * 277 cpudb_entry_create(cpudb_ref_t db_ref, const cpudb_key_t key, int is_local) 278 { 279 cpudb_entry_t *entry; 280 281 CPUDB_CHECK(db_ref, NULL); 282 283 _CPUDB_LOCK; 284 entry = _cpudb_entry_create(db_ref, key); 285 if ((entry != NULL) && (is_local)) { 286 db_ref->local_entry = entry; 287 entry->flags |= CPUDB_F_IS_LOCAL; 288 } 289 _CPUDB_UNLOCK; 290 291 return entry; 292 } 293 294 295 /* 296 * Function: 297 * cpudb_local_base_info_set 298 * Purpose: 299 * Set up local entry in db_ref according to local_entry data 300 * Parameters: 301 * db_ref - DB to update 302 * local_entry - Pointer to "local" entry data 303 * Returns: 304 * BCM_E_XXX 305 * Notes: 306 * Creates local entry if one doesn't already exist in the DB. 307 * Error if local entry exists in db_ref with a different key. 308 * Sets the "base init done" flag for the entry. 309 */ 310 311 int 312 cpudb_local_base_info_set(cpudb_ref_t db_ref, cpudb_base_t *local_base) 313 { 314 cpudb_entry_t *entry; 315 316 CPUDB_CHECK(db_ref, BCM_E_PARAM); 317 if (db_ref->local_entry == NULL) { 318 entry = cpudb_entry_create(db_ref, local_base->key, TRUE); 319 if (entry == NULL) { 320 return BCM_E_MEMORY; 321 } 322 } else { 323 if (CPUDB_KEY_COMPARE(local_base->key, 324 db_ref->local_entry->base.key) != 0) { 325 return BCM_E_EXISTS; 326 } 327 entry = db_ref->local_entry; 328 } 329 330 sal_memcpy(&entry->base, local_base, sizeof(cpudb_base_t)); 331 entry->flags |= CPUDB_F_BASE_INIT_DONE; 332 333 return BCM_E_NONE; 334 } 335 336 /* 337 * Function: 338 * cpudb_master_set 339 * Purpose: 340 * Set the entry to be the master 341 * Parameters: 342 * db_ref -- DB being updated 343 * key -- Key of the master CPU 344 * Returns: 345 * BCM_E_XXX 346 * Notes: 347 * If key is not in the DB, returns NOT_FOUND 348 */ 349 350 int 351 cpudb_master_set(cpudb_ref_t db_ref, const cpudb_key_t key) 352 { 353 cpudb_entry_t *entry; 354 355 CPUDB_CHECK(db_ref, BCM_E_PARAM); 356 CPUDB_KEY_SEARCH(db_ref, key, entry); 357 if (entry == NULL) { 358 return BCM_E_NOT_FOUND; 359 } 360 361 if (db_ref->master_entry != NULL) { 362 db_ref->master_entry->flags &= ~CPUDB_F_IS_MASTER; 363 } 364 365 db_ref->master_entry = entry; 366 entry->flags |= CPUDB_F_IS_MASTER; 367 368 return BCM_E_NONE; 369 } 370 371 372 /* 373 * Function: 374 * cpudb_master_get 375 * Purpose: 376 * Get pointer to the master entry, if set 377 * Parameters: 378 * db_ref -- The DB to examine 379 * Returns: 380 * BCM_E_XXX 381 * Notes: 382 * Returns NULL if the master is not set. 383 */ 384 385 cpudb_entry_t * 386 cpudb_master_get(cpudb_ref_t db_ref) 387 { 388 CPUDB_CHECK(db_ref, NULL); 389 390 return db_ref->master_entry; 391 } 392 393 394 /* 395 * Function: 396 * cpudb_entry_count_get 397 * Purpose: 398 * Returns the number of entries in the DB referenced. 399 * Parameters: 400 * db_ref - DB to update 401 * Returns: 402 * BCM_E_XXX < 0 if not valid; otherwise, number of entries in this DB 403 * Notes: 404 */ 405 406 int 407 cpudb_entry_count_get(cpudb_ref_t db_ref) 408 { 409 CPUDB_CHECK(db_ref, BCM_E_PARAM); 410 411 return db_ref->num_cpus; 412 } 413 414 415 /* 416 * Function: 417 * cpudb_sysid_set 418 * Purpose: 419 * Set the sysid of a CPUDB entry 420 * Parameters: 421 * db_ref - Reference to CPUDB 422 * key - Key of entry to update 423 * sysid - Value to set sysid to. 424 * overwrite - If TRUE, will overwrite existing sysid; otherwise 425 * returns exists. 426 * Returns: 427 * BCM_E_XXX 428 * Notes: 429 * Checks whether the sysid is already assigned to a different entry 430 */ 431 432 int 433 cpudb_sysid_set(cpudb_ref_t db_ref, cpudb_key_t key, void *sysid, 434 int overwrite) 435 { 436 cpudb_entry_t *entry; 437 int rv = BCM_E_NONE; 438 439 CPUDB_CHECK(db_ref, BCM_E_PARAM); 440 441 entry = cpudb_sysid_lookup(db_ref, sysid); 442 if (entry != NULL) { /* Sys ID in DB already; see if key matches */ 443 if (CPUDB_KEY_COMPARE(entry->base.key, key)) { /* memcmp semantics */ 444 return BCM_E_EXISTS; /* Key mismatch */ 445 } 446 447 return BCM_E_NONE; /* Exists, matches */ 448 } 449 450 _CPUDB_LOCK; 451 452 CPUDB_KEY_SEARCH(db_ref, key, entry); 453 if (entry == NULL) { 454 _CPUDB_UNLOCK; 455 return BCM_E_NOT_FOUND; 456 } 457 458 if (entry->flags & CPUDB_F_SYSID_KNOWN) { 459 if (overwrite) { 460 entry->sysid = sysid; 461 } else { 462 rv = BCM_E_EXISTS; 463 } 464 /* We know it doesn't match b/c the above search failed */ 465 _CPUDB_UNLOCK; 466 return rv; 467 } 468 469 entry->sysid = sysid; 470 entry->flags |= CPUDB_F_SYSID_KNOWN; 471 472 _CPUDB_UNLOCK; 473 return BCM_E_NONE; 474 } 475 476 477 /* 478 * Function: 479 * cpudb_sysid_lookup 480 * Purpose: 481 * Search DB for sysid (not efficient) 482 * Parameters: 483 * db_ref - DB to search 484 * sysid - sysid to search for 485 * Returns: 486 * Pointer to entry if found; otherwise NULL 487 */ 488 489 cpudb_entry_t * 490 cpudb_sysid_lookup(cpudb_ref_t db_ref, void *sysid) 491 { 492 cpudb_entry_t *cur; 493 494 CPUDB_CHECK(db_ref, NULL); 495 _CPUDB_LOCK; 496 CPUDB_FOREACH_ENTRY(db_ref, cur) { 497 if (cur->flags & CPUDB_F_SYSID_KNOWN && cur->sysid == sysid) { 498 _CPUDB_UNLOCK; 499 return cur; /* Found it */ 500 } 501 } 502 503 _CPUDB_UNLOCK; 504 return NULL; 505 } 506 507 /* 508 * Function: 509 * cpudb_mac_lookup 510 * Purpose: 511 * Search DB for mac (not efficient) 512 * Parameters: 513 * db_ref - DB to search 514 * mac - mac to search for 515 * Returns: 516 * Pointer to entry if found; otherwise NULL 517 * Notes: 518 * In the future, for systems with many CPUs supported, we 519 * might want to add a hash lookup for the MAC address. 520 */ 521 522 cpudb_entry_t * 523 cpudb_mac_lookup(cpudb_ref_t db_ref, const bcm_mac_t mac) 524 { 525 cpudb_entry_t *cur; 526 527 CPUDB_CHECK(db_ref, NULL); 528 _CPUDB_LOCK; 529 CPUDB_FOREACH_ENTRY(db_ref, cur) { 530 if (!sal_memcmp(cur->base.mac, mac, sizeof(bcm_mac_t))) { 531 _CPUDB_UNLOCK; 532 return cur; /* Found it */ 533 } 534 } 535 536 _CPUDB_UNLOCK; 537 return NULL; 538 } 539 540 541 /* 542 * Function: 543 * cpudb_entry_remove 544 * Purpose: 545 * Remove an entry from the CPU database by key 546 * Parameters: 547 * db_ref - DB to update 548 * key - The key to search for and remove 549 * Returns: 550 * BCM_E_XXX 551 */ 552 553 int 554 cpudb_entry_remove(cpudb_ref_t db_ref, const cpudb_key_t key) 555 { 556 cpudb_entry_t *entry; 557 558 CPUDB_CHECK(db_ref, BCM_E_PARAM); 559 _CPUDB_LOCK; 560 561 /* Check if removing entry marked local or master */ 562 if (db_ref->local_entry != NULL && 563 CPUDB_KEY_EQUAL(db_ref->local_entry->base.key, key)) { 564 db_ref->local_entry = NULL; 565 } 566 if (db_ref->master_entry != NULL && 567 CPUDB_KEY_EQUAL(db_ref->master_entry->base.key, key)) { 568 db_ref->master_entry = NULL; 569 } 570 571 CPUDB_KEY_SEARCH(db_ref, key, entry); 572 if (entry != NULL) { 573 _cpudb_unlink_entry(db_ref, entry); 574 sal_free(entry); 575 } 576 577 _CPUDB_UNLOCK; 578 return BCM_E_NONE; 579 } 580 581 582 static char cpudb_hex[] = "0123456789abcdef"; 583 584 /* 585 * Format a key into a string. 586 * This version assumes that a key is a MAC address. 587 */ 588 int 589 cpudb_key_format(cpudb_key_t key, char *buf, int len) 590 { 591 int i, n; 592 593 /* 00:11:22:33:44:55:66 */ 594 if (len < CPUDB_KEY_STRING_LEN) { 595 return BCM_E_FAIL; 596 } 597 for (i = 0; i < 6; i++) { 598 n = key.key[i]; 599 if (n > 0xf) { 600 *buf++ = cpudb_hex[(n>>4) & 0xf]; 601 } 602 *buf++ = cpudb_hex[n & 0xf]; 603 *buf++ = ':'; 604 } 605 *--buf = '\0'; 606 return BCM_E_NONE; 607 } 608 609 /* 610 * Parse a string into a key. 611 * This version assumes that a key is a MAC address. 612 */ 613 int 614 cpudb_key_parse(char *buf, cpudb_key_t *keyp) 615 { 616 int i, c1, c2; 617 char *s; 618 619 keyp->key[0] = keyp->key[1] = keyp->key[2] = 0; 620 keyp->key[3] = keyp->key[4] = keyp->key[5] = 0; 621 622 if (buf == NULL) { 623 return BCM_E_FAIL; 624 } 625 626 /* skip leading 0x if plain hex format */ 627 if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) { 628 buf += 2; 629 } 630 631 /* start at end of string and work backwards */ 632 for (s = buf; *s; s++) { 633 ; 634 } 635 636 for (i = 5; i >= 0 && s >= buf; i--) { 637 c1 = c2 = 0; 638 if (--s >= buf) { 639 if (*s >= '0' && *s <= '9') { 640 c2 = *s - '0'; 641 } else if (*s >= 'a' && *s <= 'f') { 642 c2 = *s - 'a' + 10; 643 } else if (*s >= 'A' && *s <= 'F') { 644 c2 = *s - 'A' + 10; 645 } else if (*s == ':') { 646 ; 647 } else { 648 return BCM_E_FAIL; 649 } 650 } 651 if (*s != ':' && --s >= buf) { 652 if (*s >= '0' && *s <= '9') { 653 c1 = *s - '0'; 654 } else if (*s >= 'a' && *s <= 'f') { 655 c1 = *s - 'a' + 10; 656 } else if (*s >= 'A' && *s <= 'F') { 657 c1 = *s - 'A' + 10; 658 } else if (*s == ':') { 659 ; 660 } else { 661 return BCM_E_FAIL; 662 } 663 } 664 if (s > buf && s[-1] == ':') { 665 --s; 666 } 667 keyp->key[i] = c1 << 4 | c2; 668 } 669 return BCM_E_NONE; 670 } 671 672 /**************************************************************** 673 * 674 * Internal functions 675 */ 676 677 /* Create an entry; assumes lock is held; */ 678 STATIC cpudb_entry_t * 679 _cpudb_entry_create(cpudb_t *db_ref, const cpudb_key_t key) 680 { 681 cpudb_entry_t *entry, *next, *prev; 682 int h_idx; 683 684 CPUDB_KEY_SEARCH(db_ref, key, entry); 685 686 if (entry != NULL) { 687 return entry; 688 } 689 690 entry = sal_alloc(sizeof(cpudb_entry_t), "cpudb_entry"); 691 if (entry == NULL) { 692 return NULL; 693 } 694 695 sal_memset(entry, 0, sizeof(cpudb_entry_t)); 696 CPUDB_KEY_COPY(entry->base.key, key); 697 698 /* Link into normal (sorted) list */ 699 prev = NULL; 700 CPUDB_FOREACH_ENTRY(db_ref, next) { 701 if (CPUDB_KEY_COMPARE(next->base.key, key) > 0) { 702 break; 703 } 704 prev = next; 705 } 706 entry->prev = prev; 707 entry->next = next; 708 if (entry->prev != NULL) { 709 entry->prev->next = entry; 710 } else { 711 db_ref->entries = entry; 712 } 713 if (entry->next != NULL) { 714 entry->next->prev = entry; 715 } 716 717 /* Link into hash list for key */ 718 h_idx = CPUDB_KEY_HASH(key); 719 entry->h_prev = NULL; 720 entry->h_next = db_ref->key_hash[h_idx]; 721 if (db_ref->key_hash[h_idx] != NULL) { 722 db_ref->key_hash[h_idx]->h_prev = entry; 723 } 724 db_ref->key_hash[h_idx] = entry; 725 726 entry->db_ref = db_ref; 727 728 db_ref->num_cpus++; 729 730 return entry; 731 } 732 733 /* 734 * Unlink an entry from (doubly) linked lists (including key hash list) 735 */ 736 737 STATIC void 738 _cpudb_unlink_entry(cpudb_ref_t db_ref, cpudb_entry_t *entry) 739 { 740 int h_idx; 741 742 /* Unlink from hash entry list */ 743 h_idx = CPUDB_KEY_HASH(entry->base.key); 744 if (entry->h_prev == NULL) { 745 db_ref->key_hash[h_idx] = entry->h_next; 746 } else { 747 entry->h_prev->h_next = entry->h_next; 748 } 749 if (entry->h_next != NULL) { 750 entry->h_next->h_prev = entry->h_prev; 751 } 752 753 /* Unlink entry from main list */ 754 if (entry->prev != NULL) { 755 entry->prev->next = entry->next; 756 } else { 757 db_ref->entries = entry->next; 758 } 759 if (entry->next != NULL) { 760 entry->next->prev = entry->prev; 761 } 762 db_ref->num_cpus--; 763 } 764 765 /* Create a duplicate of src in db_ref */ 766 STATIC cpudb_entry_t * 767 _cpudb_entry_duplicate(cpudb_ref_t db_ref, const cpudb_entry_t *src, 768 int is_local, int is_master) 769 { 770 cpudb_entry_t *entry; 771 772 entry = _cpudb_entry_create(db_ref, src->base.key); 773 if (entry == NULL) { 774 return NULL; 775 } 776 777 if (is_local) { 778 db_ref->local_entry = entry; 779 } 780 if (is_master) { 781 db_ref->master_entry = entry; 782 } 783 784 sal_memcpy(&entry->base, &src->base, sizeof(cpudb_base_t)); 785 sal_memcpy(&entry->sp_info, &src->sp_info, sizeof(cpudb_sp_list_t)); 786 sal_memcpy(&entry->mod_ids, &src->mod_ids, sizeof(cpudb_mod_list_t)); 787 entry->flags = src->flags; 788 entry->sysid = src->sysid; 789 entry->tx_unit = src->tx_unit; 790 entry->tx_port = src->tx_port; 791 entry->dest_mod = src->dest_mod; 792 entry->dest_port = src->dest_port; 793 entry->user_cookie = src->user_cookie; 794 entry->trans_ptr = src->trans_ptr; 795 entry->topo_idx = src->topo_idx; 796 797 return entry; 798 } 799 800 /* 801 * Function: 802 * cpudb_copy 803 * Purpose: 804 * Create a copy of a CPUDB and return a reference to it. 805 * Parameters: 806 * db_ref - which DB to copy 807 * Returns: 808 * NULL if fails; 809 * Pointer to new DB clone otherwise 810 * Note that the TOPO COOKIE is NOT duplicated. It stays 811 * NULL in the new DB since CPUDB doesn't know enough to 812 * duplicate it. 813 */ 814 815 cpudb_ref_t 816 cpudb_copy(const cpudb_ref_t src_db) 817 { 818 cpudb_ref_t new_db; 819 int error = FALSE; 820 cpudb_entry_t *current, *entry; 821 822 if (!DB_REF_VALID(src_db)) { 823 return CPUDB_REF_NULL; 824 } 825 826 new_db = cpudb_create(); 827 if (new_db == CPUDB_REF_NULL) { 828 return CPUDB_REF_NULL; 829 } 830 831 _CPUDB_LOCK; 832 CPUDB_FOREACH_ENTRY(src_db, current) { 833 entry = _cpudb_entry_duplicate(new_db, current, 834 src_db->local_entry == current, 835 src_db->master_entry == current); 836 if (entry == NULL) { 837 error = TRUE; 838 break; 839 } 840 } 841 _CPUDB_UNLOCK; 842 843 if (error) { 844 if (new_db != CPUDB_REF_NULL) { 845 cpudb_destroy(new_db); 846 } 847 return CPUDB_REF_NULL; 848 } 849 850 return new_db; 851 } 852 853 854 /* 855 * Function: 856 * cpudb_entry_copy 857 * Purpose: 858 * Copy data from one CPUDB entry to another 859 * Parameters: 860 * dest -- Pointer to destination entry 861 * src -- Pointer to source entry 862 * Returns: 863 * BCM_E_XXX 864 * Notes: 865 * Copies the user cookie directly, so be careful if this is a 866 * pointer to a resource that could go away due to the original 867 * being destroyed. 868 */ 869 870 int 871 cpudb_entry_copy(cpudb_entry_t *dest, const cpudb_entry_t *src) 872 { 873 if (dest == NULL || src == NULL) { 874 return BCM_E_PARAM; 875 } 876 877 sal_memcpy(&dest->base, &src->base, sizeof(cpudb_base_t)); 878 sal_memcpy(&dest->sp_info, &src->sp_info, sizeof(cpudb_sp_list_t)); 879 sal_memcpy(&dest->mod_ids, &src->mod_ids, sizeof(cpudb_mod_list_t)); 880 dest->flags = src->flags; 881 dest->sysid = src->sysid; 882 dest->tx_unit = src->tx_unit; 883 dest->tx_port = src->tx_port; 884 dest->dest_mod = src->dest_mod; 885 dest->dest_port = src->dest_port; 886 dest->user_cookie = src->user_cookie; 887 dest->trans_ptr = src->trans_ptr; 888 dest->topo_idx = src->topo_idx; 889 890 return BCM_E_NONE; 891 } 892 893 /* 894 * Function: 895 * cpudb_sp_idx_to_slot 896 * Purpose: 897 * Map a stack port index to the slot number and DB entry 898 * it connects to. 899 * Parameters: 900 * db_ref -- DB reference 901 * entry -- source entry 902 * sp_idx -- stack port index from source entry 903 * out_entry -- (OUT) Destination entry 904 * Returns: 905 * The slot ID of the destination if found 906 * Notes: 907 * Returns -1 if not found. 908 * Works for CFM and LM sources 909 * out_entry may be NULL 910 * Assumes sp_idx is valid for entry. 911 */ 912 913 int 914 cpudb_sp_idx_to_slot(const cpudb_ref_t db_ref, const cpudb_entry_t *entry, 915 int sp_idx, cpudb_entry_t **out_entry) 916 { 917 cpudb_entry_t *db_ent; 918 919 /* LM Source: Search DB for CFM to which the SP connects */ 920 CPUDB_KEY_SEARCH(db_ref, entry->sp_info[sp_idx].tx_cpu_key, db_ent); 921 if (db_ent == NULL) { 922 return -1; 923 } 924 925 if (out_entry != NULL) { 926 *out_entry = db_ent; 927 } 928 929 return db_ent->base.slot_id; 930 } 931 932 /* 933 * Function: 934 * cpudb_key_lookup 935 * Purpose: 936 * Search DB for key 937 * Parameters: 938 * db_ref - DB to search 939 * key - key to search for 940 * Returns: 941 * Pointer to entry if found; otherwise NULL 942 */ 943 944 cpudb_entry_t * 945 cpudb_key_lookup(cpudb_ref_t db_ref, const cpudb_key_t key) 946 { 947 cpudb_entry_t *cur; 948 949 CPUDB_CHECK(db_ref, NULL); 950 _CPUDB_LOCK; 951 CPUDB_KEY_SEARCH(db_ref, key, cur); 952 _CPUDB_UNLOCK; 953 return cur; 954 } 955 956