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-rtrans.c (6576B)


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