bcm-uk-rtrans.c (4175B)
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 * This provides a simple implementation of a BCM C2C/NH transport driver. 9 * This driver uses a User/Kernel Proxy service to transmit and receive the 10 * data. 11 * This driver is compiled for both the kernel and user space. 12 */ 13 14 #include <shared/bsl.h> 15 16 #include <sal/core/alloc.h> 17 #include <sal/core/thread.h> 18 19 #include <bcm/error.h> 20 21 #include <soc/cm.h> 22 23 #include <bcm/tx.h> 24 #include <bcm/rx.h> 25 #include <assert.h> 26 27 #include <linux-uk-proxy.h> 28 #include <bcm-uk-trans.h> 29 30 /* 31 * This is the name of the proxy service this module will use 32 */ 33 static char _input_proxy_service[] = "BCM UK PROXY REMOTE TRANSPORT"; 34 static char _output_proxy_service[] = "BCM UK PROXY REMOTE TRANSPORT"; 35 36 37 /* 38 * Receives packets from the HW, sends them to user space 39 */ 40 static bcm_rx_t 41 _bcm_rx_cb(int unit, bcm_pkt_t* pkt, void* cookie) 42 { 43 /* User space expects the bcm_pkt_t before the data */ 44 unsigned char data[LUK_MAX_DATA_SIZE]; 45 unsigned char* p = data; 46 47 /* The bcm_pkt_t structure is expected at the start of the data */ 48 /* The pointers will get fixed up in user space */ 49 memcpy(p, pkt, sizeof(*pkt)); 50 p+=sizeof(*pkt); 51 pkt->pkt_data->len = pkt->pkt_len; 52 memcpy(p, pkt->pkt_data->data, pkt->pkt_data->len); 53 54 /* Send it */ 55 linux_uk_proxy_send(_output_proxy_service, data, pkt->pkt_data->len+sizeof(*pkt)+4); 56 /* Other people might want this at this point */ 57 return BCM_RX_NOT_HANDLED; 58 } 59 60 /* 61 * Function: 62 * _rx_handle 63 * Purpose: 64 * Processes a received frame for the transport 65 */ 66 static int 67 _handle_user_tx(unsigned char* data, int len) 68 { 69 bcm_pkt_t* pkt; 70 unsigned char* p = data; 71 int l = len; 72 /* We received a packet from user space. Need to tx it */ 73 /* pkt structure is at the beginning of the packet */ 74 pkt = (bcm_pkt_t*)p; 75 p += sizeof(bcm_pkt_t); 76 l -= sizeof(bcm_pkt_t); 77 78 /* Set up the data block */ 79 pkt->pkt_data = &pkt->_pkt_data; 80 pkt->pkt_data->data = p; 81 pkt->pkt_data->len = l; 82 pkt->blk_count = 1; 83 84 bcm_tx(pkt->unit, pkt, NULL); 85 bcm_rx_free(0, data); 86 87 return 0; 88 } 89 90 91 /* 92 * Function: 93 * _rx_thread 94 * Purpose: 95 * Receives and dispatches packets from the kernel proxy service. 96 */ 97 98 typedef struct rx_thread_ctrl_s { 99 const char* service; 100 int exit; 101 } thread_ctrl_t; 102 103 static void 104 _user_tx_thread(thread_ctrl_t* ctrl) 105 { 106 unsigned char* data = NULL; 107 108 for(;;) { 109 unsigned int len = LUK_MAX_DATA_SIZE; 110 if(!data) { 111 /* Transport client expects data to be allocated from the rx buffer pool */ 112 bcm_rx_alloc(0, LUK_MAX_DATA_SIZE, 0, (void*)&data); 113 assert(data); 114 } 115 memset(data, 0, LUK_MAX_DATA_SIZE); 116 117 if(linux_uk_proxy_recv(ctrl->service, data, &len) >= 0) { 118 _handle_user_tx(data, len); 119 120 data = NULL; 121 } 122 123 if(ctrl->exit) { 124 ctrl->exit = 0; 125 return; 126 } 127 } 128 } 129 130 /* RX thread control */ 131 static thread_ctrl_t _ctrl; 132 133 int 134 bcm_uk_rtrans_create(const char* service, bcm_trans_ptr_t** trans) 135 { 136 if(service) { 137 strcpy(_input_proxy_service, service); 138 strcpy(_output_proxy_service, service); 139 } 140 141 linux_uk_proxy_service_create(_input_proxy_service, 64, 0); 142 143 _ctrl.service = _input_proxy_service; 144 _ctrl.exit = 0; 145 146 sal_thread_create("BCM UK RT", 0, 0, (void (*)(void*))_user_tx_thread, &_ctrl); 147 148 /* Register an rx handler to send packets back to user */ 149 { 150 int rc; 151 if((rc = bcm_rx_register(0, "", _bcm_rx_cb, 250, NULL, BCM_RCO_F_ALL_COS)) < 0) { 152 LOG_CLI((BSL_META("register failed: %d (%s)\n"), rc, bcm_errmsg(rc))); 153 } 154 else { 155 LOG_CLI((BSL_META("registered callback\n"))); 156 } 157 if((rc = bcm_rx_start(0, NULL)) < 0) { 158 LOG_CLI((BSL_META("start failed: %d (%s)\n"), rc, bcm_errmsg(rc))); 159 } 160 else { 161 LOG_CLI((BSL_META("rx started\n"))); 162 } 163 } 164 165 *trans = NULL; 166 return 0; 167 } 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184