BA / Mbed OS BaBoRo1
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ethernet_mac_api.c Source File

ethernet_mac_api.c

00001 /*
00002  * Copyright (c) 2016-2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "nsconfig.h"
00019 #include <string.h>
00020 #include "ethernet_mac_api.h"
00021 #include "eventOS_event.h"
00022 #include "nsdynmemLIB.h"
00023 #include "common_functions.h"
00024 #include "MAC/rf_driver_storage.h"
00025 
00026 typedef struct eth_mac_internal_s {
00027     eth_mac_api_t *mac_api;
00028     arm_device_driver_list_s *dev_driver;
00029     uint8_t *mtu_ptr;
00030     uint16_t mtu_size;
00031     uint8_t mac48[6];
00032     bool active_data_request;
00033     int8_t tasklet_id;
00034     //linked list link
00035 }eth_mac_internal_t;
00036 
00037 static eth_mac_internal_t mac_store = //Hack only at this point, later put into linked list
00038 {
00039     .tasklet_id = -1
00040 };
00041 
00042 #define ETH_INIT_EVENT 0
00043 #define ETH_DATA_IND_EVENT 1
00044 #define ETH_DATA_CNF_EVENT 2
00045 
00046 
00047 #define ETHERNET_HDROFF_DST_ADDR    0
00048 #define ETHERNET_HDROFF_SRC_ADDR    6
00049 #define ETHERNET_HDROFF_TYPE        12
00050 #define ETHERNET_HDRLEN             14
00051 
00052 static int8_t eth_mac_api_init(eth_mac_api_t *api, eth_mac_data_confirm *conf_cb, eth_mac_data_indication *ind_cb, uint8_t parent_id);
00053 static void data_req(const eth_mac_api_t* api, const eth_data_req_t *data);
00054 static int8_t mac48_address_set( const eth_mac_api_t* api, const uint8_t *mac48);
00055 static int8_t mac48_address_get( const eth_mac_api_t* api, uint8_t *mac48_buf);
00056 
00057 static int8_t eth_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len, uint8_t link_quality, int8_t dbm, int8_t driver_id);
00058 static int8_t eth_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
00059 static void ethernet_mac_tasklet(arm_event_s *event);
00060 
00061 int8_t ethernet_mac_destroy(eth_mac_api_t *mac_api)
00062 {
00063     if( !mac_api || mac_store.mac_api != mac_api ){
00064         return -1;
00065     }
00066 
00067     mac_store.active_data_request = false;
00068     ns_dyn_mem_free(mac_store.mac_api);
00069     mac_store.mac_api = NULL;
00070     mac_store.dev_driver = NULL;
00071     ns_dyn_mem_free(mac_store.mtu_ptr);
00072     mac_store.mtu_ptr = NULL;
00073     mac_store.mtu_size = 0;
00074     return 0;
00075 }
00076 
00077 
00078 
00079 eth_mac_api_t *ethernet_mac_create(int8_t driver_id)
00080 {
00081     //TODO: Refactor this away, Drivers should be stored in MAC layer in future
00082     arm_device_driver_list_s *driver = arm_net_phy_driver_pointer(driver_id);
00083     if( !driver || !driver->phy_driver){
00084         return NULL;
00085     }
00086 
00087     //Accept to return same mac if mac is generated and driver is same
00088     if (mac_store.mac_api) {
00089         if (mac_store.dev_driver == driver) {
00090             return mac_store.mac_api;
00091         }
00092         return NULL;
00093     }
00094 
00095     uint8_t *buffer_ptr = NULL;
00096     uint16_t buffer_length = 0;
00097     bool address_resolution_needed = true;
00098 
00099     switch (driver->phy_driver->link_type) {
00100 
00101         case PHY_LINK_SLIP:
00102             //Do not Allocate
00103             address_resolution_needed = false;
00104             buffer_length = 0;
00105             break;
00106 
00107         case PHY_LINK_TUN:
00108             address_resolution_needed = false;
00109             buffer_length = 1500 + 4;
00110             break;
00111         case PHY_LINK_ETHERNET_TYPE:
00112 
00113            buffer_length = 1500 + ETHERNET_HDRLEN;
00114 
00115 
00116 
00117             break;
00118 
00119         default:
00120             return NULL;
00121     }
00122     if (buffer_length) {
00123         buffer_ptr = ns_dyn_mem_alloc(buffer_length);
00124         if (!buffer_ptr) {
00125             return NULL;
00126         }
00127     }
00128 
00129     eth_mac_api_t *this = ns_dyn_mem_alloc(sizeof(eth_mac_api_t));
00130     if( !this ){
00131         ns_dyn_mem_free(buffer_ptr);
00132         return NULL;
00133     }
00134     memset(this, 0, sizeof(eth_mac_api_t));
00135     this->mac_initialize = &eth_mac_api_init;
00136     this->data_req = &data_req;
00137     this->mac48_get = &mac48_address_get;
00138     this->mac48_set = &mac48_address_set;
00139 
00140     this->address_resolution_needed = address_resolution_needed;
00141 
00142     memset(&mac_store.mac48, 0, 6);
00143     mac_store.active_data_request = false;
00144     mac_store.mac_api = this;
00145     mac_store.dev_driver = driver;
00146     mac_store.mtu_ptr = buffer_ptr;
00147     mac_store.mtu_size = buffer_length;
00148 
00149     memcpy(&mac_store.mac48, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
00150     if (mac_store.tasklet_id == -1) {
00151         mac_store.tasklet_id = eventOS_event_handler_create(&ethernet_mac_tasklet, ETH_INIT_EVENT);
00152     }
00153     arm_net_phy_init(driver->phy_driver, &eth_mac_net_phy_rx, &eth_mac_net_phy_tx_done);
00154 
00155     return this;
00156 }
00157 
00158 static void ethernet_mac_tasklet(arm_event_s *event)
00159 {
00160     uint8_t event_type = event->event_type;
00161 
00162     switch (event_type) {
00163         case ETH_DATA_IND_EVENT:{
00164             eth_data_ind_t *data_ind = event->data_ptr;
00165             mac_store.mac_api->data_ind_cb(mac_store.mac_api, data_ind);
00166             ns_dyn_mem_free(((eth_data_ind_t*)event->data_ptr)->msdu);
00167             ns_dyn_mem_free(event->data_ptr);
00168             break;
00169             }
00170         case ETH_DATA_CNF_EVENT:{
00171             eth_data_conf_t *data_conf = event->data_ptr;
00172             mac_store.mac_api->data_conf_cb(mac_store.mac_api, data_conf);
00173             ns_dyn_mem_free(event->data_ptr);
00174             mac_store.active_data_request = false;
00175             break;
00176             }
00177         case ETH_INIT_EVENT:
00178         default:{
00179             break;
00180             }
00181     }
00182 }
00183 
00184 static int8_t eth_mac_api_init( eth_mac_api_t *api, eth_mac_data_confirm *conf_cb, eth_mac_data_indication *ind_cb, uint8_t parent_id)
00185 {
00186     if( mac_store.mac_api != api ){
00187         return -1;
00188     }
00189     eth_mac_api_t *cur = mac_store.mac_api;
00190     cur->data_conf_cb = conf_cb;
00191     cur->data_ind_cb = ind_cb;
00192     cur->parent_id = parent_id;
00193 
00194     return 0;
00195 }
00196 
00197 static void data_req(const eth_mac_api_t* api, const eth_data_req_t *data)
00198 {
00199     if( mac_store.mac_api != api || !mac_store.dev_driver->phy_driver || !data  || !data->msduLength){
00200         return;
00201     }
00202 
00203 
00204     uint8_t *data_ptr;
00205     uint16_t data_length;
00206 
00207     //Build header
00208     switch (mac_store.dev_driver->phy_driver->link_type) {
00209         case PHY_LINK_ETHERNET_TYPE:
00210 
00211             if (data->msduLength + ETHERNET_HDRLEN > mac_store.mtu_size || !data->dstAddress || !data->srcAddress ) {
00212                 return;
00213             }
00214 
00215             data_ptr = mac_store.mtu_ptr;
00216             data_length = data->msduLength + ETHERNET_HDRLEN;
00217             memcpy(data_ptr + ETHERNET_HDROFF_DST_ADDR, data->dstAddress, 6);
00218             memcpy(data_ptr + ETHERNET_HDROFF_SRC_ADDR, data->srcAddress, 6);
00219             common_write_16_bit(data->etehernet_type, data_ptr + ETHERNET_HDROFF_TYPE);
00220             memcpy(data_ptr + ETHERNET_HDRLEN, data->msdu, data->msduLength);
00221             break;
00222 
00223         case PHY_LINK_TUN:
00224             if (data->msduLength + 4 > mac_store.mtu_size) {
00225                 return;
00226             }
00227             data_ptr = mac_store.mtu_ptr;
00228             /* TUN header
00229              * [ TUN FLAGS 2B | PROTOCOL 2B | PAYLOAD ]
00230              * Tun flags may be 0, and protocol is same as in ether-type field, so
00231              * replace flags with e.g. IFF_TUN and packet is converted to TUN frame
00232              */
00233             common_write_16_bit(0, data_ptr);
00234             common_write_16_bit(data->etehernet_type, data_ptr + 2);
00235             memcpy(data_ptr + 4, data->msdu, data->msduLength);
00236             data_length = data->msduLength + 4;
00237             break;
00238 
00239         default: //SLIP
00240             data_ptr = data->msdu;
00241             data_length = data->msduLength;
00242             break;
00243     }
00244 
00245     mac_store.active_data_request = true;
00246     mac_store.dev_driver->phy_driver->tx(data_ptr, data_length, 0, PHY_LAYER_PAYLOAD);
00247 }
00248 
00249 static int8_t eth_mac_net_phy_rx(const uint8_t *data_ptr, uint16_t data_len, uint8_t link_quality, int8_t dbm, int8_t driver_id)
00250 {
00251     arm_device_driver_list_s *driver = arm_net_phy_driver_pointer(driver_id);
00252     if (!data_ptr || !driver || driver != mac_store.dev_driver) {
00253         return -1;
00254     }
00255 
00256     if (data_len == 0) {
00257         return -1;
00258     }
00259 
00260     eth_data_ind_t *data_ind = ns_dyn_mem_temporary_alloc(sizeof(eth_data_ind_t));
00261     if (!data_ind){
00262         return -1;
00263     }
00264     memset(data_ind, 0, sizeof(eth_data_ind_t));
00265 
00266     if (driver->phy_driver->link_type == PHY_LINK_ETHERNET_TYPE) {
00267         if (data_len < ETHERNET_HDRLEN + 1) {
00268             ns_dyn_mem_free(data_ind);
00269             return -1;
00270         }
00271 
00272         memcpy(data_ind->dstAddress,data_ptr +  ETHERNET_HDROFF_DST_ADDR, 6);
00273         memcpy(data_ind->srcAddress,data_ptr +  ETHERNET_HDROFF_SRC_ADDR, 6);
00274 
00275         data_ind->etehernet_type = common_read_16_bit(data_ptr + ETHERNET_HDROFF_TYPE);
00276 
00277         data_ptr += ETHERNET_HDRLEN;
00278         data_len -= ETHERNET_HDRLEN;
00279 
00280     } else if (driver->phy_driver->link_type == PHY_LINK_TUN) {
00281         if (data_len < 5) {
00282             ns_dyn_mem_free(data_ind);
00283             return -1;
00284         }
00285         /* TUN header
00286          * [ TUN FLAGS 2B | PROTOCOL 2B | PAYLOAD ]
00287          * Protocol is ether-type id.
00288          */
00289         data_ind->etehernet_type = common_read_16_bit(data_ptr + 2);
00290 
00291         data_len -= 4;
00292         data_ptr += 4;
00293     } else if (driver->phy_driver->link_type == PHY_LINK_SLIP) {
00294         data_ind->etehernet_type = ETHERTYPE_IPV6;
00295     }
00296 
00297     data_ind->msdu = ns_dyn_mem_temporary_alloc(data_len);
00298     if(!data_ind->msdu){
00299         ns_dyn_mem_free(data_ind);
00300         return -1;
00301     }
00302     memcpy(data_ind->msdu, data_ptr, data_len);
00303     data_ind->msduLength = data_len;
00304     data_ind->dbm = dbm;
00305     data_ind->link_quality = link_quality;
00306 
00307     arm_event_s event = {
00308             .receiver = mac_store.tasklet_id,
00309             .sender = 0,
00310             .event_id = 0,
00311             .data_ptr = data_ind,
00312             .event_type = ETH_DATA_IND_EVENT,
00313             .priority = ARM_LIB_HIGH_PRIORITY_EVENT,
00314     };
00315 
00316     if (eventOS_event_send(&event)) {
00317         ns_dyn_mem_free(data_ind->msdu);
00318         ns_dyn_mem_free(data_ind);
00319         return -1;
00320     }
00321 
00322     return 0;
00323 }
00324 
00325 static int8_t eth_mac_net_phy_tx_done(int8_t driver_id, uint8_t tx_handle, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry)
00326 {
00327     (void)tx_handle;
00328     (void)cca_retry;
00329     (void)tx_retry;
00330     arm_device_driver_list_s *driver = arm_net_phy_driver_pointer(driver_id);
00331     if (!driver) {
00332         return -1;
00333     }
00334 
00335     if( mac_store.active_data_request ){
00336         mac_store.active_data_request = false;
00337         eth_data_conf_t *data_conf = ns_dyn_mem_temporary_alloc(sizeof(eth_data_conf_t));
00338         if (!data_conf){
00339             return -1;
00340         }
00341         data_conf->status = status;
00342         arm_event_s event = {
00343                 .receiver = mac_store.tasklet_id,
00344                 .sender = 0,
00345                 .event_id = 0,
00346                 .data_ptr = data_conf,
00347                 .event_type = ETH_DATA_CNF_EVENT,
00348                 .priority = ARM_LIB_HIGH_PRIORITY_EVENT,
00349         };
00350 
00351         return eventOS_event_send(&event);
00352     }
00353     return 0;
00354 }
00355 
00356 static int8_t mac48_address_set( const eth_mac_api_t* api, const uint8_t *mac48)
00357 {
00358     if(!mac48 || !api || mac_store.mac_api != api ){
00359         return -1;
00360     }
00361     memcpy(mac_store.mac48, mac48, 6);
00362     phy_device_driver_s *driver = mac_store.dev_driver->phy_driver;
00363     if (driver->address_write) {
00364         driver->address_write(PHY_MAC_48BIT, mac_store.mac48);
00365     }
00366     return 0;
00367 }
00368 
00369 static int8_t mac48_address_get(const eth_mac_api_t* api, uint8_t *mac48_buf)
00370 {
00371     if(!mac48_buf || !api || mac_store.mac_api != api ){
00372         return -1;
00373     }
00374     memcpy(&mac_store.mac48, mac_store.dev_driver->phy_driver->PHY_MAC, 6);
00375     memcpy(mac48_buf, mac_store.mac48, 6);
00376     return 0;
00377 }