openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 */