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

bcm-uk-trans.c (6451B)


      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 
     10  * the data. 
     11  * This driver is compiled for both the kernel and user space. 
     12  */
     13 
     14 #ifndef __KERNEL__
     15 #include <stdlib.h>
     16 #endif
     17 #include <assert.h>
     18 
     19 #include <sal/core/alloc.h>
     20 #include <sal/core/thread.h>
     21 
     22 #include <bcm/error.h>
     23 #include <soc/cm.h>
     24 
     25 #include <linux-uk-proxy.h>
     26 #include <bcm-uk-trans.h>
     27 
     28 /* 
     29  * This is the name of the proxy service this module will use 
     30  */
     31 static char _input_proxy_service[] = "BCM UK PROXY TRANSPORT"; 
     32 static char _output_proxy_service[] = "BCM UK PROXY TRANSPORT"; 
     33 
     34 
     35 /* This is the stacking port number assigned to our transport */
     36 static int _port = 0; 
     37 
     38 /*
     39  * Simple Handler registration (emphasis on simple). 
     40  */
     41 #define MAX_CALLBACKS 5
     42 static struct callback_ctrl_s {
     43     bcm_rx_cb_f cb; 
     44     void* cookie; 
     45 } _callback_ctrl[MAX_CALLBACKS]; 
     46 
     47 /*
     48  * Function:
     49  *	_rx_reg
     50  * Purpose:
     51  *	Provides the transport's rx register function. Veru minimal. 
     52  */
     53 static int
     54 _rx_reg(int unit, const char* name, bcm_rx_cb_f callback, uint8 priority, 
     55 	void* cookie, uint32 flags)
     56 {
     57     int i; 
     58     for(i = 0; i < MAX_CALLBACKS; i++) {
     59 	if(_callback_ctrl[i].cb == NULL) {
     60 	    _callback_ctrl[i].cb = callback; 
     61 	    _callback_ctrl[i].cookie = cookie; 
     62 	    return 0; 
     63 	}
     64     }
     65     return -1; 
     66 }
     67 
     68 /*
     69  * Function:
     70  *	_rx_unreg
     71  * Purpose:
     72  *	Provides the transport's rx unregister function. Very minimal. 
     73  */
     74 static int
     75 _rx_unreg(int unit, bcm_rx_cb_f callback, uint8 priority)
     76 {
     77     int i; 
     78     for(i = 0; i < MAX_CALLBACKS; i++) {
     79 	if(_callback_ctrl[i].cb == callback) {
     80 	    _callback_ctrl[i].cb = NULL; 
     81 	    _callback_ctrl[i].cookie = NULL; 
     82 	}
     83     }
     84     return 0; 
     85 }
     86 
     87 
     88 /*
     89  * Function:
     90  *	_rx_handle
     91  * Purpose:
     92  *	Processes a received frame for the transport
     93  */
     94 static int
     95 _rx_handle(unsigned char* data, int len)
     96 {
     97     int i; 
     98     bcm_pkt_t pkt;
     99     memset(&pkt, 0, sizeof(pkt)); 
    100     
    101     /* Create a bcm_pkt_t for the packet */
    102     pkt.pkt_data = &pkt._pkt_data; 
    103     
    104     pkt.pkt_data->data = data; 
    105     pkt.pkt_data->len = len; 
    106     pkt.pkt_len = len; 
    107 
    108     pkt.blk_count = 1; 
    109     pkt.unit = 0; 
    110 
    111     /* Assign our port as the ingress */
    112     pkt.rx_port = _port; 
    113     pkt.rx_unit = 0; 
    114 
    115     /* Call everyone. This does not implement the priority scheme. */
    116     for(i = 0; i < MAX_CALLBACKS; i++) {
    117 	if(_callback_ctrl[i].cb) {
    118 	    int rc = _callback_ctrl[i].cb(0, &pkt, _callback_ctrl[i].cookie); 
    119 	    switch(rc)
    120 		{
    121 		case BCM_RX_HANDLED:		    
    122 		    {
    123 			/* We should try to reuse this */
    124 			bcm_rx_free(0, data); 
    125 			return 0; 
    126 		    }
    127 		case BCM_RX_HANDLED_OWNED:
    128 		    {	
    129 			return 0; 
    130 		    }
    131 		case BCM_RX_NOT_HANDLED:
    132 		    {
    133 			/* Next handler */
    134 			break;
    135 		    }
    136 		default:
    137 		    {
    138 			assert(0); 
    139 			break;
    140 		    }
    141 		}
    142 	}
    143     }
    144     bcm_rx_free(0, data); 
    145     return 0; 
    146 }
    147 
    148 
    149 /*
    150  * Function:
    151  *	_rx_thread
    152  * Purpose:
    153  *	Receives and dispatches packets from the kernel proxy service. 
    154  */
    155 
    156 typedef struct rx_thread_ctrl_s {
    157     const char* service; 
    158     int exit; 
    159 } rx_thread_ctrl_t; 
    160 
    161 static void
    162 _rx_thread(rx_thread_ctrl_t* ctrl)
    163 {
    164     unsigned char* data = NULL; 
    165 
    166     for(;;) {
    167 	unsigned int len = LUK_MAX_DATA_SIZE; 
    168 	if(!data) {
    169 	    /* Transport client expects data to be allocated from the rx buffer pool */
    170 	    bcm_rx_alloc(0, LUK_MAX_DATA_SIZE, 0, (void*)&data); 
    171 	    assert(data); 
    172 	}
    173 	memset(data, 0, LUK_MAX_DATA_SIZE); 
    174 
    175 	if(linux_uk_proxy_recv(ctrl->service, data, &len) >= 0) {
    176 	    _rx_handle(data, len); 
    177 	    
    178 	    data = NULL; 
    179 	}
    180 	
    181 	if(ctrl->exit) {
    182 	    ctrl->exit = 0; 
    183 	    return; 
    184 	}
    185     }
    186 }
    187 	
    188 	
    189 /*
    190  * Function:
    191  *	_setup_tx
    192  * Purpose:
    193  *	setup_tx transport vector
    194  */
    195 static int
    196 _setup_tx(int unit, bcm_pkt_t* tx_pkt)
    197 {
    198     /* Nothing needed here */
    199     return BCM_E_NONE; 
    200 }
    201 
    202 /*
    203  * Function:
    204  *	_tx
    205  * Purpose:
    206  *	tx transport vector
    207  */
    208 static int
    209 _tx(int unit, bcm_pkt_t* pkt, void* cookie)
    210 {    
    211     int i; 
    212     unsigned char data[LUK_MAX_DATA_SIZE]; 
    213     unsigned char* p = data; 
    214     int len = 0; 
    215 
    216     /* Collect data blocks into one buffer for transport */
    217     for(i = 0; i < pkt->blk_count; i++) {
    218 	memcpy(p, pkt->pkt_data[i].data, pkt->pkt_data[i].len); 
    219 	p+=pkt->pkt_data[i].len; 
    220 	len += pkt->pkt_data[i].len;	
    221     }
    222     
    223     len += 4; /* CRC_APPEND -- check flag */
    224 
    225     /* Send it */    
    226     linux_uk_proxy_send(_output_proxy_service, data, len+4); 
    227     
    228     if(pkt->call_back) {
    229 	pkt->call_back(unit, pkt, cookie); 
    230     }
    231 
    232     return 0; 
    233 }	
    234 
    235 /*
    236  * Function:
    237  *	_tx_list
    238  * Purpose:
    239  *	tx_list transport vector
    240  */
    241 static int
    242 _tx_list(int unit, bcm_pkt_t* pkt, bcm_pkt_cb_f all_done_cb, void* cookie)
    243 {
    244     bcm_pkt_t* p; 
    245     
    246     /* Just tx each one */
    247     for(p = pkt; p; p = p->next) {
    248 	_tx(unit, p, cookie); 
    249     }
    250 
    251     if(all_done_cb) {
    252 	all_done_cb(unit, pkt, cookie); 
    253     }
    254 
    255     return 0; 
    256 }
    257 
    258 
    259 /*
    260  * This is our transport structure
    261  */
    262 static bcm_trans_ptr_t _trans_ptr = {
    263     bcm_rx_alloc,       /* All transports need to use bcm_rx_alloc() */
    264     bcm_rx_free,        /* and bcm_rx_free() at the moment */
    265     bcm_pkt_rx_alloc,
    266     bcm_pkt_rx_free,
    267     _rx_reg,
    268     _rx_unreg, 
    269     _setup_tx, 
    270     _tx,
    271     _tx_list,
    272     NULL, 
    273     NULL, 
    274     0                   /* Default unit for alloc/free */
    275 };
    276 
    277 
    278 /* RX thread control */
    279 static rx_thread_ctrl_t _ctrl; 
    280 
    281 int 
    282 bcm_uk_trans_create(const char* service, int port, bcm_trans_ptr_t** trans)
    283 {   
    284     if(service) {
    285 	strcpy(_input_proxy_service, service); 
    286 	strcpy(_output_proxy_service, service); 
    287     }
    288 
    289 #ifndef __KERNEL__
    290     /* In user mode we need to open the proxy driver first */ 
    291     linux_uk_proxy_open(); 
    292 
    293     /* Special overrides */
    294     if(getenv("INPUT_PROXY_SERVICE")) {
    295 	strcpy(_input_proxy_service, getenv("INPUT_PROXY_SERVICE")); 
    296     }
    297     if(getenv("OUTPUT_PROXY_SERVICE")) {
    298 	strcpy(_output_proxy_service, getenv("OUTPUT_PROXY_SERVICE")); 
    299     }
    300 
    301 #endif /* __KERNEL__ */
    302 
    303 
    304     linux_uk_proxy_service_create(_input_proxy_service, 64, 0); 
    305 
    306     _ctrl.service = _input_proxy_service; 
    307     _ctrl.exit = 0; 
    308     _port = 1; 
    309 
    310     sal_thread_create("BCM UK TR", 0, 0, (void (*)(void*))_rx_thread, &_ctrl); 
    311 
    312     *trans = &_trans_ptr; 
    313     return 0; 
    314 }