atptrans_socket.c (64165B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * File: atptrans_socket.c 9 * 10 * Purpose: ATP over Sockets 11 * 12 * This module provides support for the ATP transport 13 * to use sockets as its underlying communication mechanism. 14 * 15 * Currently, this only supported for Linux User mode 16 * chassis based systems. 17 */ 18 19 #include <shared/bsl.h> 20 21 #include <sal/types.h> 22 23 #include <shared/alloc.h> 24 #include <sal/core/libc.h> 25 #include <sal/core/thread.h> 26 27 #include <shared/util.h> 28 29 #include <bcm/error.h> 30 #include <bcm/types.h> 31 #include <bcm/init.h> 32 #include <bcm/rx.h> 33 34 #include <appl/cputrans/atptrans_socket.h> 35 #include <appl/cputrans/atp.h> 36 37 38 #ifdef INCLUDE_ATPTRANS_SOCKET 39 40 /* 41 * This implementation is built on top of a socket API interface. 42 * This means that there must be OS dependent include files to use the 43 * socket interface. To make this truly portable, this interface should 44 * be abstracted in some way. Until this is done, the ATP over Sockets 45 * implementation works for Linux user mode, but not Linux kernel mode. 46 * 47 * The socket APIs used are: 48 * socket, connect, accept, bind, listen, close, shutdown, 49 * read, write, setsockopt 50 */ 51 52 #undef ATPTRANS_SOCKET_SUPPORTED 53 54 /* 55 * Linux User mode or unix 56 */ 57 #if (defined(LINUX) || defined(unix)) && !defined(__KERNEL__) 58 #include <unistd.h> 59 #include <sys/socket.h> 60 #include <netinet/in.h> 61 #include <netinet/tcp.h> 62 #include <errno.h> 63 #define ATPTRANS_SOCKET_SUPPORTED 1 64 typedef socklen_t atptrans_socklen_t; 65 #endif /* LINUX && !__KERNEL__ */ 66 67 /* 68 * Linux Kernel mode (unsupported) 69 */ 70 #if defined(LINUX) && defined(__KERNEL__) 71 #undef ATPTRANS_SOCKET_SUPPORTED 72 #endif /* (LINUX || unix) && __KERNEL__ */ 73 74 #if defined(ATPTRANS_SOCKET_SUPPORTED) 75 76 #ifndef SHUT_RDWR 77 #define SHUT_RDWR 2 78 #endif 79 80 /* ------------------------------------------------------------------- 81 * Pack - Unpack 82 * 83 * Macros to handle byte order 84 * 85 * Note: These macros are already defined in other 86 * header files. Althought not all of the implementations 87 * are the same, they accomplish the same task. 88 */ 89 #define PACK_LONG(buf, val) _SHR_PACK_LONG(buf, val) 90 #define UNPACK_LONG(buf, val) _SHR_UNPACK_LONG(buf, val) 91 92 93 /* ------------------------------------------------------------------- 94 * Packet Header 95 * 96 * Packet header expected for each ATP-Socket transmit/receive 97 */ 98 #define PKT_LEN_OFS 0 99 #define PKT_SRC_KEY_OFS (PKT_LEN_OFS + sizeof(uint32)) 100 #define PKT_CLIENT_ID_OFS (PKT_SRC_KEY_OFS + CPUDB_KEY_BYTES) 101 #define PKT_HDR_BYTES (PKT_CLIENT_ID_OFS + sizeof(uint32)) 102 103 typedef struct atp_sock_ptk_hdr_s { 104 uint32 len; /* Number of bytes in payload (packet data) */ 105 cpudb_key_t src_key; 106 uint32 client_id; 107 } atp_sock_pkt_hdr_t; 108 109 110 /* ------------------------------------------------------------------- 111 * Semaphores - Locks 112 * 113 * Used for coordinating access to global resources 114 */ 115 static sal_mutex_t atp_sock_mlock = NULL; 116 117 #define ATP_SOCK_LOCK sal_mutex_take(atp_sock_mlock, sal_mutex_FOREVER) 118 #define ATP_SOCK_UNLOCK sal_mutex_give(atp_sock_mlock) 119 #define ATP_SOCK_INIT_DONE (atp_sock_mlock != NULL) 120 121 122 /* ------------------------------------------------------------------- 123 * Threads 124 * 125 * The ATP over Sockets module may spawn the following threads, 126 * - A Server thread to service connection requests 127 * - A Connection-RX thread for each connection to service incoming packets 128 */ 129 #define ATP_SOCK_THREAD_NAME_LEN 15 130 #define ATP_SOCK_THREAD_PRI_DEFAULT 100 131 #define ATP_SOCK_STOP_RETRIES_MAX 50 132 #define ATP_SOCK_RETRY_WAIT_US 100000 /* 100 ms */ 133 134 135 /* ------------------------------------------------------------------- 136 * Server 137 * 138 * The Server will have a thread that will listen for connection 139 * requests. 140 * 141 * Note: Current implementation supports only ONE server thread 142 * running on a system at a given time. 143 */ 144 #define ATP_SOCK_BACKLOG 5 145 #define ATP_SOCK_SERVER_LPORT_DEFAULT 20567 /* Port to listen for connections */ 146 #define ATP_SOCK_SERVER_NAME_DEFAULT "bcmATPSockS" 147 148 static int atp_sock_server_lport = -1; 149 static int atp_sock_server_lsock = -1; 150 static char atp_sock_server_thread_name[ATP_SOCK_THREAD_NAME_LEN] = 151 ATP_SOCK_SERVER_NAME_DEFAULT; 152 static volatile sal_thread_t atp_sock_server_thread_id = SAL_THREAD_ERROR; 153 static volatile int atp_sock_server_exit = FALSE; 154 155 #define ATP_SOCK_SERVER_RUNNING (atp_sock_server_thread_id != SAL_THREAD_ERROR) 156 157 158 /* Configurable parameters */ 159 static int atp_sock_cfg_thread_pri = ATP_SOCK_THREAD_PRI_DEFAULT; 160 /* Local listening port, the one we are listening on in server_conn_thread() */ 161 static int atp_sock_cfg_local_port = ATP_SOCK_SERVER_LPORT_DEFAULT; 162 /* Remote connection port */ 163 static int atp_sock_cfg_remote_port = ATP_SOCK_SERVER_LPORT_DEFAULT; 164 165 /* Unique local and remote port. */ 166 static int atp_sock_cfg_unique_lr_ports = 0; 167 168 /* ------------------------------------------------------------------- 169 * Connection 170 * 171 * Contains information for a given connection. It manages the transmitting 172 * and receiving of packets. An RX-Thread is associated for each connection. 173 * 174 * sock_fd - Socket for sending/receiving data 175 * rx_thread_name - Name of the connection receive thread 176 * rx_thread_id - ID of the connection receive thread 177 * flags - Indicates more information for connection 178 */ 179 180 #define ATP_SOCK_CONN_NAME "bcmATPSock" /* bcmATPSockXXX, where XXX = socket */ 181 182 /* Flags for Connection entry */ 183 #define ATP_SOCK_CONN_CLEAR 0x0 184 #define ATP_SOCK_CONN_VALID 0x1 /* If set, a connection exists */ 185 #define ATP_SOCK_CONN_ABORT 0x2 /* If set, connection is to be destroyed */ 186 187 typedef struct atp_sock_conn_entry_s { 188 int sock_fd; 189 char rx_thread_name[ATP_SOCK_THREAD_NAME_LEN]; 190 sal_thread_t rx_thread_id; 191 volatile uint32 flags; 192 } atp_sock_conn_entry_t; 193 194 195 196 /* ------------------------------------------------------------------- 197 * ATP over Socket DB 198 * 199 * The ATP-Socket CPU database is a link list of CPU DB entries. Each entry 200 * contains information on a given remote CPU such as CPU-key to 201 * IP mapping, connection, etc. 202 * 203 * cpu_key - Destination CPU Key 204 * ip - Destination IP address, IPv4 format 205 * ip6 - Destination IP address, IPv6 format 206 * flags - More information for CPU entry 207 * conn - Connection entry for given destination CPU 208 * next - Pointer to next entry 209 */ 210 211 /* Flags for the ATP-Socket database entry */ 212 #define ATP_SOCK_DB_CLEAR 0x0 213 #define ATP_SOCK_DB_CPU_VALID 0x1 /* If set, CPU field is known */ 214 #define ATP_SOCK_DB_IP6 0x2 /* If set, IPv6 is used; else, IPv4 */ 215 #define ATP_SOCK_DB_INSTALL 0x4 216 #define ATP_SOCK_DB_INSTALLED 0x8 217 218 typedef struct atp_sock_db_entry_s atp_sock_db_entry_t; 219 struct atp_sock_db_entry_s { 220 cpudb_key_t cpu_key; 221 bcm_ip_t ip; /* IPv4 */ 222 bcm_ip6_t ip6; /* IPv6 */ 223 atp_sock_conn_entry_t conn; 224 volatile uint32 flags; 225 atp_sock_db_entry_t *next; 226 }; 227 228 static atp_sock_db_entry_t *atp_sock_db_list = NULL; 229 230 #define ATP_SOCK_DB_FOREACH_ENTRY(_list, _entry) \ 231 for (_entry = _list; _entry != NULL; _entry = _entry->next) 232 233 static const cpudb_key_t atp_sock_cpu_key_null = {{0x0, 0x0, 0x0, 234 0x0, 0x0, 0x0}}; 235 static cpudb_key_t atp_sock_local_cpu_key; 236 237 /* Host mode ATP transport support */ 238 static bcm_trans_ptr_t host_atp_transport; 239 static bcm_trans_ptr_t *original_atp_transport; 240 241 242 243 /* ------------------------------------------------------------------- 244 * Forward function declarations 245 */ 246 247 STATIC int atptrans_socket_tx_atp(cpudb_key_t dest_key, 248 int client_id, 249 uint8 *pkt_buf, 250 int len, 251 uint32 ct_flags, 252 atp_tx_cb_f callback, 253 void *cookie); 254 255 256 /* ------------------------------------------------------------------- 257 * Function - Implementation 258 */ 259 260 /* 261 * Function: 262 * ip_to_str 263 * Purpose: 264 * Converts an IPv4 address from bcm_ip_t to string format. 265 * Parameters: 266 * str - (OUT) IP address in string format 267 * ip - IP address in bcm_ip_t format 268 * Returns: 269 * BCM_E_NONE Success 270 * BCM_E_XXX Failure 271 */ 272 273 STATIC int 274 ip_to_str(char *str, bcm_ip_t ip) 275 { 276 sal_sprintf(str, "%d.%d.%d.%d", 277 (ip >> 24) & 0xff, (ip >> 16) & 0xff, 278 (ip >> 8) & 0xff, ip & 0xff); 279 280 return BCM_E_NONE; 281 } 282 283 284 /* 285 * Function: 286 * read_n 287 * Purpose: 288 * Read 'n' bytes from the given file descriptor. 289 * Parameters: 290 * fd - File descriptor to read from 291 * buffer - (OUT) Buffer where data read is returned 292 * len - Number of bytes to read 293 * Returns: 294 * > 0 Number of actual bytes read 295 * 0 EOF, received FIN 296 * (-1) On read error 297 * Notes: 298 * 1. The routine does not return until the specified number of bytes 299 * has been read, or, an EOF or read error has ocurred. 300 * 2. If actual bytes read is less than expected, an EOF 301 * was also received. 302 */ 303 304 STATIC int 305 read_n(int fd, void *buffer, int len) 306 { 307 int n_left; /* Number of bytes left to read */ 308 int n_read; /* Number of bytes read */ 309 char *ptr; 310 311 ptr = buffer; 312 n_left = len; 313 314 while (n_left > 0) { 315 if ((n_read = read(fd, ptr, n_left)) < 0) { 316 return (-1); 317 } else if (n_read == 0) { /* EOF */ 318 break; 319 } 320 321 n_left -= n_read; 322 ptr += n_read; 323 } 324 325 return (len - n_left); 326 } 327 328 329 /* 330 * Function: 331 * write_n 332 * Purpose: 333 * Write 'n' bytes to the given file descriptor. 334 * Parameters: 335 * fd - File descriptor to write to 336 * buffer - Buffer containing data 337 * len - Number of bytes in buffer to be written 338 * Returns: 339 * >= 0 Number of actual bytes written 340 * (-1) On write error 341 * Notes: 342 * The routine does not return until the specified number of bytes 343 * has been written or a write error has ocurred. 344 */ 345 346 STATIC int 347 write_n(int fd, void *buffer, int len) 348 { 349 int n_left; /* Number of bytes left to write */ 350 int n_written; /* Number of bytes written */ 351 char *ptr; 352 353 ptr = (char *)buffer; 354 n_left = len; 355 356 while (n_left > 0) { 357 if ((n_written = write(fd, ptr, n_left)) <= 0) { 358 return (-1); 359 } 360 361 n_left -= n_written; 362 ptr += n_written; 363 } 364 365 return len; 366 } 367 368 369 /* 370 * Function: 371 * recv_pkt_hdr 372 * Purpose: 373 * Read a ATP-Socket packet header from the given file descriptor. 374 * Parameters: 375 * fd - File descriptor to read packet header from 376 * hdr - (OUT) Packet header information returned 377 * Returns: 378 * BCM_E_NONE Success, received packet header 379 * BCM_E_XXX Failure, on read error 380 */ 381 382 STATIC int 383 recv_pkt_hdr(int fd, atp_sock_pkt_hdr_t *hdr) 384 { 385 int rv = BCM_E_FAIL; 386 uint8 hdr_buffer[PKT_HDR_BYTES]; 387 int n_recv; 388 389 390 /* Read packet header buffer */ 391 n_recv = read_n(fd, (void *)hdr_buffer, sizeof(hdr_buffer)); 392 393 if (n_recv == sizeof(hdr_buffer)) { 394 /* Receive complete header */ 395 /* Unpack Packet Header */ 396 UNPACK_LONG(&hdr_buffer[PKT_LEN_OFS], hdr->len); 397 CPUDB_KEY_UNPACK(&hdr_buffer[PKT_SRC_KEY_OFS], hdr->src_key); 398 UNPACK_LONG(&hdr_buffer[PKT_CLIENT_ID_OFS], hdr->client_id); 399 400 LOG_DEBUG(BSL_LS_TKS_ATP, 401 (BSL_META("ATP-Socket: Receive packet header on socket %d, " 402 "data length %d, src_key %x:%x, client id %d\n"), 403 fd, hdr->len, hdr->src_key.key[4], hdr->src_key.key[5], 404 hdr->client_id)); 405 406 rv = BCM_E_NONE; 407 } else if (n_recv == 0) { /* EOF */ 408 LOG_VERBOSE(BSL_LS_TKS_ATP, 409 (BSL_META("ATP-Socket: Connection socket %d received FIN\n"), 410 fd)); 411 } else if (n_recv < 0) { 412 LOG_ERROR(BSL_LS_TKS_ATP, 413 (BSL_META("ATP-Socket ERROR: System error\n"))); 414 } else { 415 LOG_ERROR(BSL_LS_TKS_ATP, 416 (BSL_META("ATP-Socket ERROR: Cannot read packet header\n"))); 417 } 418 419 return rv; 420 } 421 422 423 /* 424 * Function: 425 * recv_pkt_data 426 * Purpose: 427 * Read packet data from the given file descriptor. 428 * Parameters: 429 * fd - File descriptor to read data from 430 * buffer - (OUT) Buffer where data is returned; 431 * buffer size must be at least 'n_expected' bytes 432 * n_expected - Expected packet data length 433 * Returns: 434 * BCM_E_NONE Success, received expected size packet data 435 * BCM_E_XXX Failure, 436 * . Buffer is NULL 437 * . Packet data returned is smaller than expected 438 * . Read error 439 */ 440 441 STATIC int 442 recv_pkt_data(int fd, uint8 *buffer, int n_expected) 443 { 444 int rv = BCM_E_FAIL; 445 int n_recv; 446 447 /* Read packet data */ 448 n_recv = read_n(fd, buffer, n_expected); 449 450 if (n_expected == n_recv) { 451 LOG_DEBUG(BSL_LS_TKS_ATP, 452 (BSL_META("ATP-Socket: Receive packet data on socket %d, " 453 "length %d\n"), fd, n_expected)); 454 rv = BCM_E_NONE; 455 } else if (n_recv == 0) { /* EOF */ 456 LOG_VERBOSE(BSL_LS_TKS_ATP, 457 (BSL_META("ATP-Socket: Connection socket %d received FIN\n"), 458 fd)); 459 } else if (n_recv < 0) { 460 LOG_ERROR(BSL_LS_TKS_ATP, 461 (BSL_META("ATP-Socket ERROR: System error\n"))); 462 } else { 463 /* Length of data read is not what was expected */ 464 LOG_ERROR(BSL_LS_TKS_ATP, 465 (BSL_META("ATP-Socket ERROR: Expected packet data length %d, " 466 "received %d bytes\n"), n_expected, n_recv)); 467 } 468 469 return rv; 470 } 471 472 473 /* 474 * Function: 475 * send_pkt_data 476 * Purpose: 477 * Write data to given file descriptor. 478 * Parameters: 479 * client_id - Client id where to send data to 480 * fd - File descriptor to write data to 481 * buffer - Buffer containing packet data to be sent 482 * data_len - Number of data bytes in 'buffer' to send (payload) 483 * Returns: 484 * BCM_E_NONE Success, specified number of bytes were written 485 * BCM_E_XXX Failure, 486 * . Buffer is NULL 487 * . Write error 488 */ 489 STATIC int 490 send_pkt_data(int client_id, int fd, uint8 *buffer, int data_len) 491 { 492 uint8 hdr_buffer[PKT_HDR_BYTES]; 493 int n_wrote; 494 int hdr_size; 495 496 /* Pack packet header */ 497 PACK_LONG(&hdr_buffer[PKT_LEN_OFS], data_len); 498 CPUDB_KEY_PACK(&hdr_buffer[PKT_SRC_KEY_OFS], atp_sock_local_cpu_key); 499 PACK_LONG(&hdr_buffer[PKT_CLIENT_ID_OFS], client_id); 500 501 /* Send packet header */ 502 hdr_size = sizeof(hdr_buffer); 503 n_wrote = write_n(fd, (void *)hdr_buffer, hdr_size); 504 if (n_wrote < hdr_size) { 505 LOG_ERROR(BSL_LS_TKS_ATP, 506 (BSL_META("ATP-Socket ERROR: Cannot send packet header\n"))); 507 return BCM_E_FAIL; 508 } 509 510 /* Send packet data */ 511 n_wrote = write_n(fd, buffer, data_len); 512 if (n_wrote < data_len) { 513 LOG_ERROR(BSL_LS_TKS_ATP, 514 (BSL_META("ATP-Socket ERROR: Cannot send packet data, " 515 "payload length %d, sent %d\n"), data_len, n_wrote)); 516 return BCM_E_FAIL; 517 } 518 519 LOG_DEBUG(BSL_LS_TKS_ATP, 520 (BSL_META("ATP-Socket: Send packet on socket %d, " 521 "payload length %d, src key " CPUDB_KEY_FMT 522 ", client id %d\n"), fd, data_len, 523 CPUDB_KEY_DISP(atp_sock_local_cpu_key), client_id)); 524 525 return BCM_E_NONE; 526 } 527 528 529 /* 530 * Function: 531 * rx_conn_thread 532 * Purpose: 533 * Thread that processes incoming packets for a given connection. 534 * 535 * It expects an ATP-Socket packet header and the correspoding packet data. 536 * Once the payload is received, it gives the packet data to the upper 537 * layer transport protocol ATP to handle it. It then proceeds to wait 538 * for another ATP-Socket packet to arrive. 539 * 540 * Thread terminates on, 541 * . Read error 542 * . Closed connection socket 543 * . ABORT flag set 544 * 545 * Parameters: 546 * cookie - Pointer to DB entry for RX thread 547 * Returns: 548 * None 549 */ 550 551 STATIC void 552 rx_conn_thread(void *cookie) 553 { 554 int rv = BCM_E_FAIL; 555 atp_sock_pkt_hdr_t hdr; 556 uint8 *buffer; 557 int data_len; 558 bcm_rx_t pkt_rtn_code; 559 int rx_sock; 560 atp_sock_db_entry_t *db_ptr; 561 atp_sock_conn_entry_t *conn_ptr; 562 bcm_ip_t dest_ip = 0; 563 char dest_ip_str[SAL_IPADDR_STR_LEN]; 564 int lock_set = FALSE; 565 char thread_name[SAL_THREAD_NAME_MAX_LEN]; 566 sal_thread_t thread; 567 568 db_ptr = (atp_sock_db_entry_t *)cookie; 569 conn_ptr = &db_ptr->conn; 570 571 rx_sock = conn_ptr->sock_fd; 572 573 LOG_VERBOSE(BSL_LS_TKS_ATP, 574 (BSL_META("ATP-Socket: Start RX Connection Thread, socket %d\n"), 575 rx_sock)); 576 thread = sal_thread_self(); 577 thread_name[0] = 0; 578 sal_thread_name(thread, thread_name, sizeof (thread_name)); 579 /* Main loop to service incoming data for the connection */ 580 while (!(conn_ptr->flags & ATP_SOCK_CONN_ABORT)) { 581 582 /* Get packet header */ 583 rv = recv_pkt_hdr(rx_sock, &hdr); 584 if (BCM_FAILURE(rv) || (conn_ptr->flags & ATP_SOCK_CONN_ABORT)) { 585 break; 586 } 587 588 /* Get packet data */ 589 data_len = hdr.len; 590 buffer = atp_rx_data_alloc(data_len); 591 if (buffer == NULL) { 592 LOG_ERROR(BSL_LS_TKS_ATP, 593 (BSL_META("AbnormalThreadExit:%s ERROR: Cannot allocate receive " 594 "buffer\n"), thread_name)); 595 rv = BCM_E_MEMORY; 596 break; 597 } 598 599 if (hdr.len != 0) { 600 rv = recv_pkt_data(rx_sock, buffer, data_len); 601 if (BCM_FAILURE(rv) || (conn_ptr->flags & ATP_SOCK_CONN_ABORT)) { 602 atp_rx_free(buffer, NULL); 603 break; 604 } 605 } 606 607 /* 608 * Pass packet data to ATP receive routine to continue with 609 * normal processing of packet 610 */ 611 pkt_rtn_code = atp_rx_inject(hdr.src_key, hdr.client_id, 612 buffer, data_len); 613 614 switch(pkt_rtn_code) { 615 case BCM_RX_HANDLED_OWNED: 616 /* 617 * Packet was handled and stolen, do not do anything. 618 * New owner is responsible of deallocating the buffer. 619 */ 620 rv = BCM_E_NONE; 621 break; 622 623 case BCM_RX_INVALID: 624 case BCM_RX_NOT_HANDLED: 625 case BCM_RX_HANDLED: 626 default: 627 /* Need to deallocate buffer */ 628 atp_rx_free(buffer, NULL); 629 break; 630 } 631 } 632 633 close(rx_sock); 634 635 636 /* Cleanup connection entry */ 637 638 /* 639 * Get lock only if ABORT flag is not set 640 * 641 * Note: 642 * The routine that set the ABORT flag holds the lock 643 * and waits for this thread to exit. If this 644 * thread tries to get the lock, the routine waiting 645 * for this thread to exit will timeout with an error. 646 */ 647 if (!(conn_ptr->flags & ATP_SOCK_CONN_ABORT)) { 648 ATP_SOCK_LOCK; 649 lock_set = TRUE; 650 } 651 652 dest_ip = db_ptr->ip; 653 654 /* Uninstall the socket mechanism from ATP transport and update flags */ 655 if (db_ptr->flags & ATP_SOCK_DB_INSTALLED) { 656 /* Uninstall sockets from ATP */ 657 rv = atp_tx_override_set(db_ptr->cpu_key, NULL); 658 db_ptr->flags &= ~ATP_SOCK_DB_INSTALLED; 659 } 660 661 db_ptr->conn.sock_fd = -1; 662 db_ptr->conn.rx_thread_name[0] = '\0'; 663 db_ptr->conn.rx_thread_id = SAL_THREAD_ERROR; 664 db_ptr->conn.flags = ATP_SOCK_CONN_CLEAR; 665 666 if (lock_set) { 667 ATP_SOCK_UNLOCK; 668 } 669 670 ip_to_str(dest_ip_str, dest_ip); 671 LOG_DEBUG(BSL_LS_TKS_ATP, 672 (BSL_META("ATP-Socket: Destroy connection to '%s', socket %d\n"), 673 dest_ip_str, rx_sock)); 674 if (BCM_FAILURE(rv)) { 675 LOG_ERROR(BSL_LS_TKS_ATP, 676 (BSL_META("AbnormalThreadExit:%s\n"), 677 thread_name)); 678 } 679 sal_thread_exit(rv); 680 681 return; 682 } 683 684 685 /* 686 * Function: 687 * conn_destroy 688 * Purpose: 689 * It destroys a connection as follows: 690 * - Sets the ABORT flag to indicate the RX thread to exit 691 * - Closes the connection socket 692 * - Waits for the RX thread to exit for a period of time 693 * Parameters: 694 * db_ptr - Pointer to DB entry to destroy connection 695 * Returns: 696 * BCM_E_NONE Success 697 * BCM_E_XXX Failure, 698 * . RX connection thread did not exit in expected wait time 699 * Note: 700 * Assumes LOCK is held by caller 701 */ 702 703 STATIC int 704 conn_destroy(atp_sock_db_entry_t *db_ptr) 705 { 706 int i; 707 708 if (!(db_ptr->conn.flags & ATP_SOCK_CONN_VALID)) { 709 return BCM_E_NONE; 710 } 711 712 db_ptr->conn.flags |= ATP_SOCK_CONN_ABORT; 713 shutdown(db_ptr->conn.sock_fd, SHUT_RDWR); 714 715 /* Wait until connection is clear */ 716 for (i = 0; i < ATP_SOCK_STOP_RETRIES_MAX; i++) { 717 if (db_ptr->conn.rx_thread_id == SAL_THREAD_ERROR) { 718 break; 719 } 720 sal_usleep(ATP_SOCK_RETRY_WAIT_US); 721 } 722 723 if (i >= ATP_SOCK_STOP_RETRIES_MAX) { 724 LOG_ERROR(BSL_LS_TKS_ATP, 725 (BSL_META("ATP-Socket ERROR: Cannot destroy connection on " 726 "socket %d\n"), db_ptr->conn.sock_fd)); 727 return BCM_E_FAIL; 728 } 729 730 return BCM_E_NONE; 731 } 732 733 734 /* 735 * Function: 736 * conn_create 737 * Purpose: 738 * It creates a connection as follows: 739 * - Checks that DB entry does not have a valid connection, 740 * if so, return failure 741 * - Creates an RX connection thread 742 * - Sets ATP override to use sockets 743 * - Updates the connection information on corresponding DB entry 744 * Parameters: 745 * db_ptr - Pointer to DB entry to create connection for 746 * sock_fd - Connection socket 747 * Returns: 748 * BCM_E_NONE Success 749 * BCM_E_XXX Failure, 750 * . DB entry contains a valid connection 751 * . Cannot create thread 752 * Note: 753 * Assumes LOCK is held by caller 754 */ 755 756 STATIC int 757 conn_create(atp_sock_db_entry_t *db_ptr, int sock_fd) 758 { 759 int rv; 760 atp_sock_conn_entry_t *conn_ptr; 761 char thread_name[ATP_SOCK_THREAD_NAME_LEN]; 762 sal_thread_t thread_id = SAL_THREAD_ERROR; 763 const int sock_opt_on = 1; 764 char dest_ip_str[SAL_IPADDR_STR_LEN]; 765 766 767 /* 768 * Set socket option to disable Nagle algorithm. 769 * The purpose is to increase performance. 770 * 771 * Note: The Nagle algorithm prevents a connection from 772 * having multiple outstanding packets at any time. 773 * It waits for the 'ack' to come back before it sends 774 * any packet. 775 */ 776 setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, 777 (char *)&sock_opt_on, sizeof(sock_opt_on)); 778 779 /* Create RX connection thread */ 780 sal_snprintf(thread_name, ATP_SOCK_THREAD_NAME_LEN, 781 "%s%d", ATP_SOCK_CONN_NAME, sock_fd); 782 783 conn_ptr = &db_ptr->conn; 784 if (conn_ptr->flags & ATP_SOCK_CONN_VALID) { 785 LOG_ERROR(BSL_LS_TKS_ATP, 786 (BSL_META("ATP-Socket ERROR: Connection already exists\n"))); 787 return BCM_E_EXISTS; 788 } 789 790 /* Set information */ 791 conn_ptr->flags = ATP_SOCK_CONN_VALID; 792 conn_ptr->sock_fd = sock_fd; 793 794 /* Create thread to handle specific connection request */ 795 sal_strcpy(conn_ptr->rx_thread_name, thread_name); 796 thread_id = sal_thread_create(conn_ptr->rx_thread_name, 797 SAL_THREAD_STKSZ, 798 atp_sock_cfg_thread_pri, 799 rx_conn_thread, 800 (void *) db_ptr); 801 802 if (thread_id == SAL_THREAD_ERROR) { 803 conn_ptr->flags = ATP_SOCK_CONN_CLEAR; 804 conn_ptr->sock_fd = -1; 805 conn_ptr->rx_thread_name[0]='\0'; 806 LOG_ERROR(BSL_LS_TKS_ATP, 807 (BSL_META("ATP-Socket ERROR: Cannot create connection thread\n"))); 808 return BCM_E_FAIL; 809 } 810 811 conn_ptr->rx_thread_id = thread_id; 812 813 /* Install on ATP if needed */ 814 if (db_ptr->flags & ATP_SOCK_DB_INSTALL) { 815 /* Set ATP to use sockets */ 816 rv = atp_tx_override_set(db_ptr->cpu_key, atptrans_socket_tx_atp); 817 if (BCM_SUCCESS(rv)) { 818 db_ptr->flags |= ATP_SOCK_DB_INSTALLED; 819 } 820 } 821 822 ip_to_str(dest_ip_str, db_ptr->ip); 823 LOG_DEBUG(BSL_LS_TKS_ATP, 824 (BSL_META("ATP-Socket: Created connection to '%s', socket %d, " 825 "thread '%s'\n"), 826 dest_ip_str, conn_ptr->sock_fd, 827 conn_ptr->rx_thread_name)); 828 829 return BCM_E_NONE; 830 } 831 832 833 834 /* 835 * Function: 836 * conn_request 837 * Purpose: 838 * It request a connection to the destination IP specified in the 839 * DB entry. If successful, a connection is created and the DB 840 * entry is updated. 841 * Parameters: 842 * db_ptr - Pointer to DB entry of destination CPU to 843 * connect to 844 * Returns: 845 * >= 0 Socket for requested connection, if successful 846 * < 0 Failure to establish connection 847 * Note: 848 * Assumes LOCK is held by caller 849 */ 850 851 STATIC int 852 conn_request(atp_sock_db_entry_t *db_ptr) 853 { 854 struct sockaddr_in server_addr; 855 atptrans_socklen_t addr_len; 856 int conn_sock = -1; 857 char dest_ip_str[SAL_IPADDR_STR_LEN]; 858 int rv = -1; 859 860 ip_to_str(dest_ip_str, db_ptr->ip); 861 862 LOG_VERBOSE(BSL_LS_TKS_ATP, 863 (BSL_META("ATP-Socket: Connection request to '%s'\n"), 864 dest_ip_str)); 865 866 /* Open socket */ 867 if ((conn_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 868 LOG_ERROR(BSL_LS_TKS_ATP, 869 (BSL_META("ATP-Socket ERROR: Cannot open socket (err=%d)\n"), 870 conn_sock)); 871 return conn_sock; 872 } 873 874 /* Connect to specified destination */ 875 addr_len = (atptrans_socklen_t) sizeof(server_addr); 876 877 sal_memset((void *)&server_addr, 0, (int)addr_len); 878 server_addr.sin_family = AF_INET; 879 server_addr.sin_port = htons(atp_sock_cfg_remote_port); 880 server_addr.sin_addr.s_addr = htonl(db_ptr->ip); 881 882 if ((rv = connect(conn_sock, 883 (struct sockaddr *) &server_addr, addr_len)) < 0) { 884 LOG_ERROR(BSL_LS_TKS_ATP, 885 (BSL_META("ATP-Socket ERROR: \ 886 Cannot connect to '%s'; port %d (err=%d)\n"), 887 dest_ip_str, atp_sock_cfg_remote_port, rv)); 888 close(conn_sock); 889 return rv; 890 } 891 892 rv = conn_create(db_ptr, conn_sock); 893 if (BCM_FAILURE(rv)) { 894 LOG_ERROR(BSL_LS_TKS_ATP, 895 (BSL_META("ATP-Socket ERROR: Cannot create TX connection to '%s', " 896 "closing socket %d\n"), dest_ip_str, conn_sock)); 897 close(conn_sock); 898 return rv; 899 } 900 901 902 LOG_VERBOSE(BSL_LS_TKS_ATP, 903 (BSL_META("ATP-Socket: Connection established with '%s' on socket " 904 "%d\n"), dest_ip_str, conn_sock)); 905 906 return conn_sock; 907 } 908 909 910 /* 911 * Function: 912 * db_cpu_key_lookup 913 * Purpose: 914 * It searches for a matching CPU key in the database list. 915 * Parameters: 916 * list - Database list 917 * cpu_key - CPU key to lookup 918 * Returns: 919 * non-null Pointer to matching entry 920 * null CPU key not found 921 * Note: 922 * Assumes LOCK is held by caller 923 */ 924 925 STATIC atp_sock_db_entry_t * 926 db_cpu_key_lookup(atp_sock_db_entry_t *list, cpudb_key_t cpu_key) 927 { 928 atp_sock_db_entry_t *entry; 929 930 ATP_SOCK_DB_FOREACH_ENTRY(list, entry) { 931 if (entry->flags & ATP_SOCK_DB_CPU_VALID) { 932 if (CPUDB_KEY_EQUAL(entry->cpu_key, cpu_key)) { 933 return entry; 934 } 935 } 936 } 937 938 return entry; 939 } 940 941 /* 942 * Function: 943 * db_ip_lookup 944 * Purpose: 945 * It searches for a matching IP address in the database list. 946 * Parameters: 947 * list - Database list 948 * ip - IP address to lookup 949 * Returns: 950 * non-null Pointer to matching entry 951 * null IP address not found 952 * Note: 953 * Assumes LOCK is held by caller 954 */ 955 956 STATIC atp_sock_db_entry_t * 957 db_ip_lookup(atp_sock_db_entry_t *list, bcm_ip_t ip) 958 { 959 atp_sock_db_entry_t *entry; 960 961 ATP_SOCK_DB_FOREACH_ENTRY(list, entry) { 962 if (entry->ip == ip) { 963 return entry; 964 } 965 } 966 967 return entry; 968 } 969 970 971 /* 972 * Function: 973 * sock_get 974 * Purpose: 975 * It gets the socket for the given CPU key. 976 * Parameters: 977 * list - Database list to search 978 * dest_key - CPU key 979 * Returns: 980 * >=0 Socket number 981 * -1 Failure, no valid connection was found for given CPU 982 * Note: 983 * Assumes LOCK is held by caller 984 */ 985 986 STATIC int 987 sock_get(atp_sock_db_entry_t *list, cpudb_key_t dest_key) 988 { 989 int sock_fd = -1; 990 atp_sock_db_entry_t *db_ptr; 991 992 if ((db_ptr = db_cpu_key_lookup(list, dest_key)) != NULL) { 993 if ((db_ptr->conn.flags & ATP_SOCK_CONN_VALID) && 994 !(db_ptr->conn.flags & ATP_SOCK_CONN_ABORT)) { 995 sock_fd = db_ptr->conn.sock_fd; 996 } 997 } 998 999 return sock_fd; 1000 } 1001 1002 /* 1003 * Function: 1004 * db_insert_front 1005 * Purpose: 1006 * It inserts given DB entry to the front of the database list. 1007 * Parameters: 1008 * list - (IN/OUT) Database list 1009 * entry - Pointer to DB entry to insert to list 1010 * Returns: 1011 * Pointer to database list 1012 * Note: 1013 * Assumes LOCK is held by caller 1014 */ 1015 1016 STATIC atp_sock_db_entry_t * 1017 db_insert_front(atp_sock_db_entry_t **list, atp_sock_db_entry_t *entry) 1018 { 1019 /* Insert entry */ 1020 entry->next = *list; 1021 *list = entry; 1022 1023 return *list; 1024 } 1025 1026 1027 /* 1028 * Function: 1029 * db_entry_create 1030 * Purpose: 1031 * It performs one of the following: 1032 * - If entry already exists in database list, it checks that 1033 * the CPU and/or IP address values are consistent with 1034 * input values. 1035 * - Else, it creates a new DB entry and adds it to the given ATP-Socket 1036 * database list. 1037 * Parameters: 1038 * list - (IN/OUT) Database list 1039 * cpu_key - CPU key 1040 * ip - IP address, IPv4 format 1041 * flags - Should be set as follows, 1042 * ATP_SOCK_DB_CPU_VALID if CPU key is provided 1043 * ATP_SOCK_DB_INSTALL if sockets is to be installed 1044 * Returns: 1045 * BCM_E_NONE Success 1046 * BCM_E_XXX Failure, 1047 * . Entry already exists with unconsistent values 1048 * . Cannot allocate memory 1049 * Note: 1050 * Assumes LOCK is held by caller 1051 */ 1052 1053 STATIC atp_sock_db_entry_t * 1054 db_entry_create(atp_sock_db_entry_t **list, 1055 cpudb_key_t const cpu_key, bcm_ip_t ip, uint32 flags) 1056 { 1057 int rv; 1058 atp_sock_db_entry_t *cpu_key_match; 1059 atp_sock_db_entry_t *ip_match; 1060 atp_sock_db_entry_t *entry; 1061 1062 ip_match = db_ip_lookup(*list, ip); 1063 1064 if (flags & ATP_SOCK_DB_CPU_VALID) { 1065 cpu_key_match = db_cpu_key_lookup(*list, cpu_key); 1066 if ((cpu_key_match != NULL) && (cpu_key_match != ip_match)) { 1067 return NULL; 1068 } 1069 } 1070 1071 if ((atp_sock_cfg_unique_lr_ports == 1) && 1072 (ip_match != NULL) && 1073 (CPUDB_KEY_COMPARE(ip_match->cpu_key, cpu_key))) { 1074 /* If local and remote ports are not same, 1075 * Ignore the entry allocated for other port. 1076 */ 1077 entry = NULL; 1078 } else { 1079 entry = ip_match; 1080 } 1081 1082 if (entry != NULL) { 1083 if (flags & ATP_SOCK_DB_CPU_VALID) { 1084 1085 /* If CPU is known, check that keys are same */ 1086 if (entry->flags & ATP_SOCK_DB_CPU_VALID) { 1087 if (CPUDB_KEY_COMPARE(entry->cpu_key, cpu_key)) { 1088 return NULL; 1089 } 1090 } else { 1091 /* Copy CPU key if needed */ 1092 CPUDB_KEY_COPY(entry->cpu_key, cpu_key); 1093 } 1094 1095 /* Install on ATP if needed */ 1096 if (((flags & ATP_SOCK_DB_INSTALL) && 1097 !(entry->flags & ATP_SOCK_DB_INSTALLED)) && 1098 (entry->conn.flags & ATP_SOCK_CONN_VALID)) { 1099 /* Set ATP to use Sockets */ 1100 rv = atp_tx_override_set(entry->cpu_key, 1101 atptrans_socket_tx_atp); 1102 if (BCM_SUCCESS(rv)) { 1103 entry->flags |= ATP_SOCK_DB_INSTALLED; 1104 } 1105 } 1106 } 1107 entry->flags |= flags; 1108 return entry; 1109 } 1110 1111 1112 /* Allocate new entry */ 1113 entry = sal_alloc(sizeof(atp_sock_db_entry_t), "atp_sock_db_entry"); 1114 if (entry == NULL) { 1115 return NULL; 1116 } 1117 1118 /* Set information */ 1119 CPUDB_KEY_COPY(entry->cpu_key, cpu_key); 1120 entry->ip = ip; 1121 entry->flags = flags; 1122 entry->conn.sock_fd = -1; 1123 entry->conn.rx_thread_name[0] = '\0'; 1124 entry->conn.rx_thread_id = SAL_THREAD_ERROR; 1125 entry->conn.flags = ATP_SOCK_CONN_CLEAR; 1126 entry->next = NULL; 1127 1128 db_insert_front(list, entry); 1129 1130 LOG_DEBUG(BSL_LS_TKS_ATP, 1131 (BSL_META("ATP-Socket: Added CPU key " CPUDB_KEY_FMT "\n"), 1132 CPUDB_KEY_DISP(entry->cpu_key))); 1133 1134 return entry; 1135 } 1136 1137 1138 /* 1139 * Function: 1140 * db_entry_remove 1141 * Purpose: 1142 * Removes the given DB entry from the specified ATP-Socket database list. 1143 * If a valid connection exists for given entry, this is destroyed. 1144 * Parameters: 1145 * list - (IN/OUT) Database list 1146 * db_ptr - Pointer to DB entry to remove 1147 * Returns: 1148 * BCM_E_NONE Success 1149 * BCM_E_XXX Failure 1150 * Note: 1151 * Assumes LOCK is held by caller 1152 */ 1153 1154 STATIC int 1155 db_entry_remove(atp_sock_db_entry_t **list, atp_sock_db_entry_t *db_ptr) 1156 { 1157 int rv; 1158 atp_sock_db_entry_t *prev; 1159 atp_sock_db_entry_t *cur; 1160 1161 rv = conn_destroy(db_ptr); 1162 if (BCM_FAILURE(rv)) { 1163 return BCM_E_FAIL; 1164 } 1165 1166 prev = NULL; 1167 1168 ATP_SOCK_DB_FOREACH_ENTRY(*list, cur) { 1169 if (cur == db_ptr) { 1170 if (prev == NULL) { 1171 *list = cur->next; 1172 } else { 1173 prev->next = cur->next; 1174 } 1175 sal_free(cur); 1176 return BCM_E_NONE; 1177 } 1178 prev = cur; 1179 } 1180 1181 return BCM_E_NOT_FOUND; 1182 } 1183 1184 1185 /* 1186 * Function: 1187 * accept_connection 1188 * Purpose: 1189 * It waits for a connection request and updates the ATP-Socket database 1190 * accordingly. 1191 * 1192 * On a incoming connection request, it searches the database 1193 * list for the client IP address. If client is not found, a 1194 * new DB entry is created and added to the database list. A 1195 * connection is created for the corresponding DB entry. 1196 * 1197 * If client already has a valid connection, this routine 1198 * will return a failure. 1199 * 1200 * Parameters: 1201 * listen_sock - Port to listen to for connection requests 1202 * Returns: 1203 * BCM_E_NONE Success 1204 * BCM_E_XXX Failure, 1205 * . Error on listening socket 1206 * . Could not create DB entry 1207 * . Could not create connection 1208 * . A valid connection already exists 1209 */ 1210 1211 STATIC int 1212 accept_connection(int listen_sock) 1213 { 1214 int rv; 1215 atptrans_socklen_t addr_len; 1216 struct sockaddr_in client_addr; 1217 char dest_ip_str[SAL_IPADDR_STR_LEN]; 1218 bcm_ip_t dest_ip; 1219 atp_sock_db_entry_t *db_ptr; 1220 int conn_sock; /* Connection socket */ 1221 1222 1223 addr_len = (atptrans_socklen_t) sizeof(client_addr); 1224 1225 rv = accept(listen_sock, 1226 (struct sockaddr *) &client_addr, &addr_len); 1227 1228 if (rv < 0) { 1229 LOG_VERBOSE(BSL_LS_TKS_ATP, 1230 (BSL_META("ATP-Socket: Accept returned error on socket %d " 1231 "(rv=%d)\n"), listen_sock, rv)); 1232 return BCM_E_FAIL; 1233 } 1234 1235 /* Got a connection request, process it */ 1236 conn_sock = rv; 1237 1238 /* in_addr.s_addr always in network order; bcm_ip_t in host order */ 1239 dest_ip = ntohl(client_addr.sin_addr.s_addr); 1240 ip_to_str(dest_ip_str, dest_ip); 1241 1242 LOG_VERBOSE(BSL_LS_TKS_ATP, 1243 (BSL_META("ATP-Socket: Connection request from client '%s' on " 1244 "socket %d\n"), dest_ip_str, conn_sock)); 1245 1246 if (BCM_FAILURE(rv)) { 1247 LOG_WARN(BSL_LS_TKS_ATP, 1248 (BSL_META("ATP-Socket WARNING: Invalid IP address '%s', closing " 1249 "socket %d\n"), dest_ip_str, conn_sock)); 1250 close(conn_sock); 1251 return BCM_E_NONE; 1252 } 1253 1254 ATP_SOCK_LOCK; 1255 1256 /* If destination IP is not found, create a new entry */ 1257 if ((db_ptr = db_ip_lookup(atp_sock_db_list, dest_ip)) == NULL) { 1258 if ((db_ptr = db_entry_create(&atp_sock_db_list, 1259 atp_sock_cpu_key_null, dest_ip, 1260 ATP_SOCK_DB_CLEAR)) == NULL) { 1261 ATP_SOCK_UNLOCK; 1262 LOG_WARN(BSL_LS_TKS_ATP, 1263 (BSL_META("ATP-Socket ERROR: Cannot create new entry, " 1264 "closing socket %d\n"), conn_sock)); 1265 close(conn_sock); 1266 return BCM_E_NONE; 1267 } 1268 } 1269 1270 /* Check that connection does not exist */ 1271 if (db_ptr->conn.flags & ATP_SOCK_CONN_VALID) { 1272 ATP_SOCK_UNLOCK; 1273 LOG_WARN(BSL_LS_TKS_ATP, 1274 (BSL_META("ATP-Socket ERROR: Connection already exists, closing " 1275 "socket %d\n"), conn_sock)); 1276 close(conn_sock); 1277 return BCM_E_NONE; 1278 } 1279 1280 /* Create connection */ 1281 rv = conn_create(db_ptr, conn_sock); 1282 if (BCM_FAILURE(rv)) { 1283 ATP_SOCK_UNLOCK; 1284 LOG_WARN(BSL_LS_TKS_ATP, 1285 (BSL_META("ATP-Socket WARNING: Cannot create connection to '%s', " 1286 "closing socket %d\n"), dest_ip_str, conn_sock)); 1287 close(conn_sock); 1288 return BCM_E_NONE; 1289 } 1290 1291 ATP_SOCK_UNLOCK; 1292 1293 return BCM_E_NONE; 1294 } 1295 1296 1297 /* 1298 * Function: 1299 * server_conn_thread 1300 * Purpose: 1301 * Out-Of-Band Server thread that listens for connection requests. 1302 * For each connection request, it spawns a new thread that will 1303 * handle incoming packets from the connection request originator. 1304 * Parameters: 1305 * cookie - Pointer to Server listening port 1306 * Returns: 1307 * None 1308 */ 1309 1310 STATIC void 1311 server_conn_thread(void *cookie) 1312 { 1313 int rv = 0; 1314 int listen_port = 0; 1315 int listen_sock = 0; /* Listening socket */ 1316 const int sock_opt_on = 1; 1317 atptrans_socklen_t addr_len; 1318 struct sockaddr_in server_addr; 1319 1320 1321 listen_port = *((int *)cookie); 1322 1323 /* Open socket */ 1324 if ((rv = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 1325 LOG_ERROR(BSL_LS_TKS_ATP, 1326 (BSL_META("ATP-Socket ERROR: Cannot open Server listening socket " 1327 "(err=%d)\n"), rv)); 1328 atp_sock_server_thread_id = SAL_THREAD_ERROR; 1329 sal_thread_exit(rv); 1330 return; 1331 } 1332 1333 listen_sock = rv; 1334 1335 /* 1336 * Set socket option to allow server to restart, in case 1337 * there are existing connections using the listening port 1338 */ 1339 setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, 1340 (char *)&sock_opt_on, sizeof(sock_opt_on)); 1341 1342 /* Bind socket to listen to any IP address and to a known port */ 1343 addr_len = (atptrans_socklen_t) sizeof(server_addr); 1344 sal_memset((void *)&server_addr, 0, (int)addr_len); 1345 server_addr.sin_family = AF_INET; 1346 server_addr.sin_port = htons(listen_port); 1347 server_addr.sin_addr.s_addr = htonl(INADDR_ANY); 1348 if ((rv = bind (listen_sock, 1349 (struct sockaddr *) &server_addr, addr_len)) < 0) { 1350 LOG_ERROR(BSL_LS_TKS_ATP, 1351 (BSL_META("ATP-Socket ERROR: Cannot bind Server listening " 1352 "socket %d (err=%d)\n"), listen_sock, rv)); 1353 close(listen_sock); 1354 atp_sock_server_thread_id = SAL_THREAD_ERROR; 1355 sal_thread_exit(rv); 1356 return; 1357 } 1358 1359 /* Set the socket to listen for connection requests */ 1360 if ((rv = listen(listen_sock, ATP_SOCK_BACKLOG)) < 0) { 1361 LOG_ERROR(BSL_LS_TKS_ATP, 1362 (BSL_META("ATP-Socket ERROR: Cannot set Server listening mode " 1363 "on socket %d (err=%d)\n"), listen_sock, rv)); 1364 close(listen_sock); 1365 atp_sock_server_thread_id = SAL_THREAD_ERROR; 1366 sal_thread_exit(rv); 1367 return; 1368 } 1369 1370 atp_sock_server_lport = listen_port; 1371 atp_sock_server_lsock = listen_sock; 1372 1373 LOG_VERBOSE(BSL_LS_TKS_ATP, 1374 (BSL_META("ATP-Socket: Server ready, listening on socket %d\n"), 1375 atp_sock_server_lsock)); 1376 1377 /* Main loop to service connection requests */ 1378 atp_sock_server_exit = FALSE; 1379 while (!atp_sock_server_exit) { 1380 1381 rv = accept_connection(atp_sock_server_lsock); 1382 1383 if (BCM_FAILURE(rv)) { 1384 break; 1385 } 1386 } 1387 close(atp_sock_server_lsock); 1388 1389 LOG_VERBOSE(BSL_LS_TKS_ATP, 1390 (BSL_META("ATP-Socket: Exit Server Thread '%s', " 1391 "close socket %d\n"), atp_sock_server_thread_name, 1392 atp_sock_server_lsock)); 1393 1394 ATP_SOCK_LOCK; 1395 1396 atp_sock_server_lsock = -1; 1397 atp_sock_server_lport = -1; 1398 atp_sock_server_thread_id = SAL_THREAD_ERROR; 1399 1400 ATP_SOCK_UNLOCK; 1401 1402 sal_thread_exit(rv); 1403 1404 return; 1405 } 1406 1407 1408 /* 1409 * Function: 1410 * atptrans_socket_tx_atp 1411 * Purpose: 1412 * Transmit data packet to specified destination CPU using 1413 * sockets. 1414 * 1415 * When sockets is 'installed' for the specified destination CPU, 1416 * this routine is called for any ATP TX operation. 1417 * 1418 * It checks for an existing connection. If found, existing TX 1419 * socket is used. Otherwise, a new connection request is made 1420 * and the connection table is updated. 1421 * 1422 * Parameters: 1423 * dest_key - Destination CPU to send to 1424 * client_id - Client ID to send to 1425 * pkt_buf - Buffer containing data to send 1426 * len - Length of packet data in bytes 1427 * ct_flags - Bitmap of flags passed in (N/A) 1428 * callback - If not NULL, do async and callback (N/A) 1429 * cookie - Passed on callback (N/A) 1430 * Returns: 1431 * BCM_E_NONE Success 1432 * BCM_E_XXX Failure, 1433 * . NULL packet buffer 1434 * . Could not find valid connection for given CPU 1435 * . Error sending packet 1436 */ 1437 1438 STATIC int 1439 atptrans_socket_tx_atp(cpudb_key_t dest_key, 1440 int client_id, 1441 uint8 *pkt_buf, 1442 int len, 1443 uint32 ct_flags, 1444 atp_tx_cb_f callback, 1445 void *cookie) 1446 { 1447 int rv; 1448 int conn_sock; 1449 1450 if (pkt_buf == NULL) { 1451 return BCM_E_FAIL; 1452 } 1453 1454 /* Check for flag semantics */ 1455 if (ct_flags & CPUTRANS_NO_HEADER_ALLOC) { 1456 len -= CPUTRANS_HEADER_BYTES; 1457 pkt_buf += CPUTRANS_HEADER_BYTES; 1458 } 1459 1460 /* Get socket */ 1461 ATP_SOCK_LOCK; 1462 if ((conn_sock = sock_get(atp_sock_db_list, dest_key)) < 0) { 1463 ATP_SOCK_UNLOCK; 1464 return BCM_E_FAIL; 1465 } 1466 1467 /* Send message */ 1468 rv = send_pkt_data(client_id, conn_sock, pkt_buf, len); 1469 1470 ATP_SOCK_UNLOCK; 1471 1472 LOG_DEBUG(BSL_LS_TKS_ATP, 1473 (BSL_META("ATP-Socket: Send packet on socket %d\n"), 1474 conn_sock)); 1475 1476 if (callback != NULL) { 1477 callback(pkt_buf, cookie, rv); 1478 } 1479 1480 return rv; 1481 } 1482 1483 1484 /* 1485 * Function: 1486 * cleanup 1487 * Purpose: 1488 * It cleanups the ATP over Sockets subsystem as follows, 1489 * - For each entry in the database list, 1490 * . Destroys connection if valid 1491 * . Uninstalls the socket interface and removes entry from list 1492 * - Stops the ATP-Socket Server 1493 * Parameters: 1494 * None 1495 * Returns: 1496 * None 1497 */ 1498 1499 STATIC void 1500 cleanup (void) 1501 { 1502 atp_sock_db_entry_t *db_ptr; 1503 1504 LOG_VERBOSE(BSL_LS_TKS_ATP, 1505 (BSL_META("ATP-Socket: Cleanup\n"))); 1506 1507 ATP_SOCK_LOCK; 1508 1509 /* Uninstall the socket interface */ 1510 ATP_SOCK_DB_FOREACH_ENTRY(atp_sock_db_list, db_ptr) { 1511 atptrans_socket_uninstall(db_ptr->cpu_key); 1512 } 1513 1514 ATP_SOCK_UNLOCK; 1515 1516 /* Stop the ATP-Socket Server */ 1517 atptrans_socket_server_stop(); 1518 1519 return; 1520 } 1521 1522 1523 /* 1524 * Function: 1525 * init 1526 * Purpose: 1527 * It initializes the ATP over Sockets subsystem: 1528 * - If needed, destroys current connections, uninstalls, and 1529 * clears the database list 1530 * - Destroys current mutex lock and creates a new one 1531 * - Initializes database list 1532 * - Reset configuration parameters to default values 1533 * Parameters: 1534 * None 1535 * Returns: 1536 * BCM_E_NONE Success 1537 * BCM_E_XXX Failure, 1538 * . Cannot create mutex lock 1539 */ 1540 1541 STATIC int 1542 init(void) 1543 { 1544 LOG_VERBOSE(BSL_LS_TKS_ATP, 1545 (BSL_META("ATP-Socket: Init\n"))); 1546 1547 /* System resources cleanup, if needed */ 1548 if (ATP_SOCK_INIT_DONE) { 1549 cleanup(); 1550 } 1551 1552 /* Mutex locks */ 1553 if (atp_sock_mlock != NULL) { 1554 sal_mutex_destroy(atp_sock_mlock); 1555 atp_sock_mlock = NULL; 1556 } 1557 if ((atp_sock_mlock = sal_mutex_create("ATP_Socket_mlock")) == NULL) { 1558 LOG_ERROR(BSL_LS_TKS_ATP, 1559 (BSL_META("ATP-Socket ERROR: Cannot create mutex\n"))); 1560 return BCM_E_MEMORY; 1561 } 1562 1563 atp_sock_db_list = NULL; 1564 1565 CPUDB_KEY_COPY(atp_sock_local_cpu_key, atp_sock_cpu_key_null); 1566 1567 return BCM_E_NONE; 1568 } 1569 1570 /* If atptrans_socket is started without any usable RX units, 1571 initialize the RX pool only, and use rx_pool allocators 1572 for the ATP transport allocators. 1573 1574 */ 1575 1576 STATIC int 1577 _atptrans_socket_host(void) 1578 { 1579 int rv = BCM_E_NONE; 1580 int attached; 1581 int rx_units; 1582 int i; 1583 bcm_trans_ptr_t *atp_transport; 1584 1585 rv = bcm_attach_max(&attached); 1586 1587 if (BCM_SUCCESS(rv)) { 1588 1589 /* Count how many units have RX available */ 1590 for (i=rx_units=0; i<attached; i++) { 1591 if (!bcm_rx_active(i)) { 1592 rv = bcm_rx_init(i); 1593 if (BCM_SUCCESS(rv)) { 1594 rx_units++; 1595 } 1596 } else { 1597 rx_units++; 1598 } 1599 } 1600 1601 if (rx_units == 0) { 1602 rv = atp_config_get(NULL, NULL, &atp_transport); 1603 if (BCM_SUCCESS(rv) && atp_transport != &host_atp_transport) { 1604 1605 /* Set up RX pool if needed */ 1606 if (!bcm_rx_pool_setup_done()) { 1607 rv = bcm_rx_pool_setup(-1, -1); 1608 } 1609 1610 /* Save original transport */ 1611 original_atp_transport = atp_transport; 1612 1613 /* Set up host transport */ 1614 host_atp_transport = *atp_transport; 1615 host_atp_transport.tp_data_alloc = bcm_rx_pool_alloc; 1616 host_atp_transport.tp_data_free = bcm_rx_pool_free; 1617 rv = atp_config_set(-1, -1, &host_atp_transport); 1618 } 1619 } else { 1620 /* Found RX units, so host mode is not appropriate */ 1621 rv = BCM_E_NONE; 1622 } 1623 } 1624 1625 1626 return rv; 1627 } 1628 1629 /* If atptrans_socket was started in host mode above, restore the 1630 original ATP transport structure. 1631 */ 1632 1633 STATIC int 1634 _atptrans_socket_host_stop(void) 1635 { 1636 int rv = BCM_E_NONE; 1637 if (original_atp_transport) { 1638 rv = atp_config_set(-1, -1, original_atp_transport); 1639 original_atp_transport = NULL; 1640 } 1641 1642 return rv; 1643 } 1644 1645 /* 1646 * Function: 1647 * atptrans_socket_server_start 1648 * Purpose: 1649 * Initializes the ATP over Sockets subsystem (if it has not been yet), and 1650 * it creates the Server thread. 1651 * Parameters: 1652 * None 1653 * Returns: 1654 * BCM_E_NONE Success, ATP-Socket Server created and ready for connection 1655 * requests. 1656 * BCM_E_XXX Failure, 1657 * . Server thread is running 1658 * . Cannot create Server thread 1659 * Note: 1660 * 1. Only one ATP-Socket Server can be running at a time. 1661 * 2. Supported only in chassis based systems. 1662 */ 1663 1664 int 1665 atptrans_socket_server_start(void) 1666 { 1667 int rv; 1668 1669 LOG_VERBOSE(BSL_LS_TKS_ATP, 1670 (BSL_META("ATP-Socket: Start Server\n"))); 1671 1672 rv = _atptrans_socket_host(); 1673 if (BCM_FAILURE(rv)) { 1674 return rv; 1675 } 1676 1677 if (!ATP_SOCK_INIT_DONE) { 1678 rv = init(); 1679 if (BCM_FAILURE(rv)) { 1680 return rv; 1681 } 1682 } 1683 1684 ATP_SOCK_LOCK; 1685 1686 if (ATP_SOCK_SERVER_RUNNING) { 1687 ATP_SOCK_UNLOCK; 1688 LOG_WARN(BSL_LS_TKS_ATP, 1689 (BSL_META("ATP-Socket: Server thread is already running\n"))); 1690 return BCM_E_EXISTS; 1691 } 1692 1693 /* Create Server thread */ 1694 atp_sock_server_thread_id = sal_thread_create(atp_sock_server_thread_name, 1695 SAL_THREAD_STKSZ, 1696 atp_sock_cfg_thread_pri, 1697 server_conn_thread, 1698 (void *) 1699 &atp_sock_cfg_local_port); 1700 1701 if (atp_sock_server_thread_id == SAL_THREAD_ERROR) { 1702 ATP_SOCK_UNLOCK; 1703 LOG_ERROR(BSL_LS_TKS_ATP, 1704 (BSL_META("ATP-Socket ERROR: Cannot create Server thread\n"))); 1705 return BCM_E_FAIL; 1706 } 1707 1708 ATP_SOCK_UNLOCK; 1709 1710 LOG_DEBUG(BSL_LS_TKS_ATP, 1711 (BSL_META("ATP-Socket: Created Server Thread '%s'\n"), 1712 atp_sock_server_thread_name)); 1713 1714 return BCM_E_NONE; 1715 } 1716 1717 1718 /* 1719 * Function: 1720 * atptrans_socket_server_stop 1721 * Purpose: 1722 * It stops the ATP-Socket Server. It closes Server listening socket 1723 * and destroys the corresponding Server thread. The routine 1724 * only returns after the Server thread has exited or has 1725 * exceeded the waiting time. 1726 * Parameters: 1727 * None 1728 * Returns: 1729 * BCM_E_NONE Success, Server thread exited 1730 * BCM_E_XXX Failure, Server thread did not exit in expected wait time 1731 * Note: 1732 * Supported only in chassis based systems 1733 */ 1734 1735 int 1736 atptrans_socket_server_stop(void) 1737 { 1738 int i; 1739 1740 if (!ATP_SOCK_INIT_DONE) { 1741 return BCM_E_NONE; 1742 } 1743 1744 LOG_VERBOSE(BSL_LS_TKS_ATP, 1745 (BSL_META("ATP-Socket: Stop Server\n"))); 1746 1747 ATP_SOCK_LOCK; 1748 1749 if (!ATP_SOCK_SERVER_RUNNING) { 1750 ATP_SOCK_UNLOCK; 1751 LOG_VERBOSE(BSL_LS_TKS_ATP, 1752 (BSL_META("ATP-Socket: Server not running\n"))); 1753 return BCM_E_NONE; 1754 } 1755 1756 /* Force Server thread to exit */ 1757 atp_sock_server_exit = TRUE; 1758 shutdown(atp_sock_server_lsock, SHUT_RDWR); 1759 1760 ATP_SOCK_UNLOCK; 1761 1762 /* Wait for server thread to exit */ 1763 for (i = 0; i < ATP_SOCK_STOP_RETRIES_MAX; i++) { 1764 if (!ATP_SOCK_SERVER_RUNNING) { 1765 break; 1766 } 1767 sal_usleep(ATP_SOCK_RETRY_WAIT_US); 1768 } 1769 1770 if (i >= ATP_SOCK_STOP_RETRIES_MAX) { 1771 LOG_ERROR(BSL_LS_TKS_ATP, 1772 (BSL_META("ATP-Socket ERROR: Cannot stop Server Thread in %d ms\n"), 1773 (ATP_SOCK_STOP_RETRIES_MAX * ATP_SOCK_RETRY_WAIT_US)/1000)); 1774 return BCM_E_FAIL; 1775 } 1776 1777 _atptrans_socket_host_stop(); 1778 1779 /* Reset configuration parameters to default values */ 1780 atp_sock_cfg_thread_pri = ATP_SOCK_THREAD_PRI_DEFAULT; 1781 atp_sock_cfg_local_port = ATP_SOCK_SERVER_LPORT_DEFAULT; 1782 atp_sock_cfg_remote_port = ATP_SOCK_SERVER_LPORT_DEFAULT; 1783 1784 return BCM_E_NONE; 1785 } 1786 1787 1788 /* 1789 * Function: 1790 * atptrans_socket_server_running 1791 * Purpose: 1792 * It indicates whether the ATP-Socket Server is currently running. 1793 * Parameters: 1794 * None 1795 * Returns: 1796 * TRUE, Server is running 1797 * FALSE, Server is not running 1798 * Note: 1799 * Supported only in chassis based systems 1800 */ 1801 1802 int 1803 atptrans_socket_server_running(void) 1804 { 1805 return ATP_SOCK_SERVER_RUNNING; 1806 } 1807 1808 1809 /* 1810 * Function: 1811 * atptrans_socket_config_set 1812 * Purpose: 1813 * It sets the configuration values. 1814 * Parameters: 1815 * priority - Priority for new threads 1816 * listen_port - Listening port for client connection request 1817 * connect_port - Connection port for server connection request 1818 * Returns: 1819 * BCM_E_NONE Success 1820 * BCM_E_XXX Failure 1821 * Note: 1822 * 1. Supported only in chassis based systems. 1823 * 2. New values will only take effect on newly create threads. 1824 * 3. A value of 0 (or negative) will leave the parameter unchanged. 1825 */ 1826 1827 int 1828 atptrans_socket_config_set(int priority, int listen_port, int connect_port) 1829 { 1830 int rv; 1831 1832 if (!ATP_SOCK_INIT_DONE) { 1833 rv = init(); 1834 if (BCM_FAILURE(rv)) { 1835 return rv; 1836 } 1837 } 1838 1839 if (priority >= 0) { 1840 atp_sock_cfg_thread_pri = priority; 1841 } 1842 if (listen_port >= 0) { 1843 atp_sock_cfg_local_port = listen_port; 1844 } 1845 if (connect_port >= 0) { 1846 atp_sock_cfg_remote_port = connect_port; 1847 } 1848 1849 /* Mark ports are unique if they are not same. */ 1850 if (atp_sock_cfg_remote_port != atp_sock_cfg_local_port) { 1851 atp_sock_cfg_unique_lr_ports = 1; 1852 } else { 1853 atp_sock_cfg_unique_lr_ports = 0; 1854 } 1855 1856 LOG_VERBOSE(BSL_LS_TKS_ATP, 1857 (BSL_META("ATP-Socket: Configuration set to priority %d, " 1858 "listen (local) port %d, connect (remote) port %d\n"), 1859 atp_sock_cfg_thread_pri, atp_sock_cfg_local_port, 1860 atp_sock_cfg_remote_port)); 1861 1862 return BCM_E_NONE; 1863 } 1864 1865 1866 /* 1867 * Function: 1868 * atptrans_socket_install 1869 * Purpose: 1870 * It installs the socket interface as the underlying 1871 * communication mechanism for the ATP transport between the 1872 * local and the given destination CPU. 1873 * 1874 * A new DB entry is created and added to the ATP-Socket database list. 1875 * 1876 * If the local CPU is the Client and destination CPU is the Server, 1877 * a connection request is made to the destination CPU. Otherwise, 1878 * it is expected that the remote destination CPU, the Client, will 1879 * be making the request. 1880 * 1881 * In any case, the 'install' flag is set so that when a connection 1882 * is finally made, the ATP override is set to use the socket interface. 1883 * 1884 * Parameters: 1885 * dest_cpu - Destination CPU key to transmit over sockets 1886 * dest_ip - Destination CPU IP address 1887 * flags - Flags 1888 * 1889 * Returns: 1890 * BCM_E_NONE Success 1891 * BCM_E_XXX Failure, 1892 * - Initialization failure 1893 * - Entry exists with conflicting values (different key or IP) 1894 * - Cannot create entry 1895 * 1896 * Note: 1897 * 1. Supported only in chassis based systems 1898 * 1899 * 2. The installation model will allow only Clients to make 1900 * connection requests. This prevents problems caused by 1901 * racing conditions. 1902 * 1903 * 3. The selection of Client and Server in a pair of CPUs is as follows, 1904 * Client - CPU with LOWER key value 1905 * Server - CPU with HIGHER key value 1906 */ 1907 1908 int 1909 atptrans_socket_install(cpudb_key_t dest_cpu_key, 1910 bcm_ip_t dest_ip, uint32 flags) 1911 { 1912 int rv; 1913 atp_sock_db_entry_t *db_ptr; 1914 char dest_ip_str[SAL_IPADDR_STR_LEN]; 1915 1916 /* Initialize ATP over Sockets subsystem if needed */ 1917 if (!ATP_SOCK_INIT_DONE) { 1918 rv = init(); 1919 if (BCM_FAILURE(rv)) { 1920 return rv; 1921 } 1922 } 1923 1924 LOG_DEBUG(BSL_LS_TKS_ATP, 1925 (BSL_META("ATP-Socket: Install CPU key " 1926 CPUDB_KEY_FMT_EOLN), 1927 CPUDB_KEY_DISP(dest_cpu_key))); 1928 1929 ATP_SOCK_LOCK; 1930 1931 /* Add to the database list */ 1932 if ((db_ptr = db_entry_create(&atp_sock_db_list, 1933 dest_cpu_key, dest_ip, 1934 ATP_SOCK_DB_CPU_VALID | 1935 ATP_SOCK_DB_INSTALL | flags )) == NULL) { 1936 ATP_SOCK_UNLOCK; 1937 LOG_ERROR(BSL_LS_TKS_ATP, 1938 (BSL_META("ATP-Socket ERROR: Cannot add new entry for CPU key " 1939 CPUDB_KEY_FMT_EOLN), 1940 CPUDB_KEY_DISP(dest_cpu_key))); 1941 return BCM_E_FAIL; 1942 } 1943 1944 if (db_ptr->flags & ATP_SOCK_DB_INSTALLED) { 1945 ATP_SOCK_UNLOCK; 1946 return BCM_E_NONE; 1947 } 1948 1949 /* 1950 * Request connection 1951 * 1952 * Connection requests are made only by Clients. The 'Client' is 1953 * the entity with the lowest value on a pair of CPU keys. In our case, 1954 * this is the local and destination CPU key pair. 1955 */ 1956 if (CPUDB_KEY_COMPARE(atp_sock_local_cpu_key, dest_cpu_key) < 0) { 1957 if ((conn_request(db_ptr)) < 0) { 1958 ATP_SOCK_UNLOCK; 1959 return BCM_E_FAIL; 1960 } 1961 } 1962 1963 1964 ATP_SOCK_UNLOCK; 1965 1966 ip_to_str(dest_ip_str, db_ptr->ip); 1967 LOG_VERBOSE(BSL_LS_TKS_ATP, 1968 (BSL_META("ATP-Socket: Installed on CPU key " CPUDB_KEY_FMT "), '%s'\n"), 1969 CPUDB_KEY_DISP(db_ptr->cpu_key), dest_ip_str)); 1970 1971 return BCM_E_NONE; 1972 } 1973 1974 1975 /* 1976 * Function: 1977 * atptrans_socket_uninstall 1978 * Purpose: 1979 * It uninstalls the socket interface and restores the default 1980 * communication mechanism for the ATP transport between the 1981 * local and the destination CPU. 1982 * 1983 * The corresponding entry is removed from the database list. 1984 * 1985 * If entry has a valid connection, this is destroyed. The ATP 1986 * override is cleared and ATP reverts to its normal transmit operation 1987 * for specified CPU. 1988 * 1989 * Parameters: 1990 * dest_cpu - Destination CPU to remove the socket interface 1991 * Returns: 1992 * BCM_E_NONE Success 1993 * BCM_E_XXX Failure 1994 * Note: 1995 * Supported only in chassis based systems 1996 */ 1997 1998 int 1999 atptrans_socket_uninstall(cpudb_key_t dest_cpu_key) 2000 { 2001 int rv; 2002 atp_sock_db_entry_t *db_ptr; 2003 2004 if (!ATP_SOCK_INIT_DONE) { 2005 LOG_ERROR(BSL_LS_TKS_ATP, 2006 (BSL_META("ATP-Socket ERROR: Not initialized\n"))); 2007 return BCM_E_FAIL; 2008 } 2009 2010 LOG_DEBUG(BSL_LS_TKS_ATP, 2011 (BSL_META("ATP-Socket: Uninstall CPU key " 2012 CPUDB_KEY_FMT_EOLN), 2013 CPUDB_KEY_DISP(dest_cpu_key))); 2014 2015 ATP_SOCK_LOCK; 2016 2017 if ((db_ptr = db_cpu_key_lookup(atp_sock_db_list, 2018 dest_cpu_key)) == NULL) { 2019 ATP_SOCK_UNLOCK; 2020 LOG_ERROR(BSL_LS_TKS_ATP, 2021 (BSL_META("ATP-Socket ERROR: Cannot find valid entry for CPU key " 2022 CPUDB_KEY_FMT_EOLN), 2023 CPUDB_KEY_DISP(dest_cpu_key))); 2024 return BCM_E_NOT_FOUND; 2025 } 2026 2027 rv = db_entry_remove(&atp_sock_db_list, db_ptr); 2028 2029 ATP_SOCK_UNLOCK; 2030 2031 if (BCM_FAILURE(rv)) { 2032 LOG_VERBOSE(BSL_LS_TKS_ATP, 2033 (BSL_META("ATP-Socket: Uninstalled failed\n"))); 2034 return BCM_E_FAIL; 2035 } 2036 2037 return BCM_E_NONE; 2038 } 2039 2040 2041 /* 2042 * Function: 2043 * atptrans_socket_local_cpu_key_set 2044 * Purpose: 2045 * Sets the key for the local CPU. 2046 * Parameters: 2047 * cpu_key - Local CPU key 2048 * Returns: 2049 * BCM_E_NONE Success 2050 * BCM_E_XXX Failure 2051 * Note: 2052 * 1. The local CPU key SHOULD be set before the install is called 2053 * 2. Supported only in chassis based systems 2054 */ 2055 2056 int 2057 atptrans_socket_local_cpu_key_set(cpudb_key_t const cpu_key) 2058 { 2059 int rv; 2060 2061 if (!ATP_SOCK_INIT_DONE) { 2062 rv = init(); 2063 if (BCM_FAILURE(rv)) { 2064 return rv; 2065 } 2066 } 2067 2068 ATP_SOCK_LOCK; 2069 CPUDB_KEY_COPY(atp_sock_local_cpu_key, cpu_key); 2070 ATP_SOCK_UNLOCK; 2071 2072 LOG_DEBUG(BSL_LS_TKS_ATP, 2073 (BSL_META("ATP-Socket: Set local CPU key " CPUDB_KEY_FMT "\n"), 2074 CPUDB_KEY_DISP(atp_sock_local_cpu_key))); 2075 2076 return BCM_E_NONE; 2077 } 2078 2079 2080 /* 2081 * Function: 2082 * atptrans_socket_show 2083 * Purpose: 2084 * It displays detailed information for the ATP over Sockets subsystem. 2085 * Parameters: 2086 * None 2087 * Returns: 2088 * None 2089 * Note: 2090 * Supported only in chassis based systems 2091 */ 2092 2093 void 2094 atptrans_socket_show(void) 2095 { 2096 char ip_str[SAL_IPADDR_STR_LEN]; 2097 atp_sock_db_entry_t *db_ptr; 2098 2099 /* Initialize if needed */ 2100 if (!ATP_SOCK_INIT_DONE) { 2101 LOG_INFO(BSL_LS_TKS_ATP, 2102 (BSL_META("ATP over Sockets not initialized\n"))); 2103 return; 2104 } 2105 2106 /* Server */ 2107 LOG_INFO(BSL_LS_TKS_ATP, 2108 (BSL_META("ATP-Socket Server\n"))); 2109 if (atptrans_socket_server_running()) { 2110 LOG_INFO(BSL_LS_TKS_ATP, 2111 (BSL_META(" Listening Port %d\n"), 2112 atp_sock_server_lport)); 2113 LOG_INFO(BSL_LS_TKS_ATP, 2114 (BSL_META(" Listening Socket %d\n"), 2115 atp_sock_server_lsock)); 2116 LOG_INFO(BSL_LS_TKS_ATP, 2117 (BSL_META(" Thread-Name %s\n"), 2118 atp_sock_server_thread_name)); 2119 } else { 2120 LOG_INFO(BSL_LS_TKS_ATP, 2121 (BSL_META(" Not running\n"))); 2122 } 2123 LOG_INFO(BSL_LS_TKS_ATP, 2124 (BSL_META("\n"))); 2125 2126 /* Database List */ 2127 LOG_INFO(BSL_LS_TKS_ATP, 2128 (BSL_META("ATP-Socket Database\n"))); 2129 LOG_INFO(BSL_LS_TKS_ATP, 2130 (BSL_META(" CPU Key IP Address Flags Socket " 2131 "Thread\n"))); 2132 LOG_INFO(BSL_LS_TKS_ATP, 2133 (BSL_META(" ----------------- --------------- ----- ------ " 2134 "-----------\n"))); 2135 ATP_SOCK_DB_FOREACH_ENTRY(atp_sock_db_list, db_ptr) { 2136 ip_to_str(ip_str, db_ptr->ip); 2137 LOG_INFO(BSL_LS_TKS_ATP, 2138 (BSL_META(" %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x %-15s 0x%3.3x"), 2139 SAL_MAC_ADDR_LIST(db_ptr->cpu_key.key), 2140 ip_str, 2141 db_ptr->flags)); 2142 2143 /* Connection */ 2144 if (db_ptr->conn.flags & ATP_SOCK_CONN_VALID) { 2145 LOG_INFO(BSL_LS_TKS_ATP, 2146 (BSL_META(" %6d %-11s"), 2147 db_ptr->conn.sock_fd, 2148 db_ptr->conn.rx_thread_name)); 2149 } 2150 2151 LOG_INFO(BSL_LS_TKS_ATP, 2152 (BSL_META("\n"))); 2153 } 2154 LOG_INFO(BSL_LS_TKS_ATP, 2155 (BSL_META("\n"))); 2156 2157 return; 2158 } 2159 2160 #else /* ATPTRANS_SOCKET_SUPPORTED */ 2161 2162 int 2163 atptrans_socket_server_start(void) 2164 { 2165 return BCM_E_UNAVAIL; 2166 } 2167 2168 int 2169 atptrans_socket_server_stop(void) 2170 { 2171 return BCM_E_UNAVAIL; 2172 } 2173 2174 int 2175 atptrans_socket_server_running(void) 2176 { 2177 return FALSE; 2178 } 2179 2180 int 2181 atptrans_socket_config_set(int priority, int listen_port, int connect_port) 2182 { 2183 COMPILER_REFERENCE(priority); 2184 COMPILER_REFERENCE(listen_port); 2185 COMPILER_REFERENCE(connect_port); 2186 return BCM_E_UNAVAIL; 2187 } 2188 2189 int 2190 atptrans_socket_install(cpudb_key_t dest_cpu_key, 2191 bcm_ip_t dest_ip, uint32 flags) 2192 { 2193 COMPILER_REFERENCE(dest_cpu_key); 2194 COMPILER_REFERENCE(dest_ip); 2195 COMPILER_REFERENCE(flags); 2196 return BCM_E_UNAVAIL; 2197 } 2198 2199 int 2200 atptrans_socket_uninstall(cpudb_key_t dest_cpu_key) 2201 { 2202 COMPILER_REFERENCE(dest_cpu_key); 2203 return BCM_E_UNAVAIL; 2204 } 2205 2206 int 2207 atptrans_socket_local_cpu_key_set(cpudb_key_t const cpu_key) 2208 { 2209 COMPILER_REFERENCE(cpu_key); 2210 return BCM_E_UNAVAIL; 2211 } 2212 2213 void 2214 atptrans_socket_show(void) 2215 { 2216 return; 2217 } 2218 2219 #endif /* ATPTRANS_SOCKET_SUPPORTED */ 2220 2221 #endif /* INCLUDE_ATPTRANS_SOCKET */