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 (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