diff options
Diffstat (limited to 'src/ipcpd/shim-eth-llc')
| -rw-r--r-- | src/ipcpd/shim-eth-llc/main.c | 114 | ||||
| -rw-r--r-- | src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto | 10 | 
2 files changed, 107 insertions, 17 deletions
| diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index 6046d939..d4ea8eba 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -20,10 +20,11 @@   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */ -#include <ouroboros/config.h> -  #define _DEFAULT_SOURCE +#define OUROBOROS_PREFIX "ipcpd/shim-eth-llc" + +#include <ouroboros/config.h>  #include <ouroboros/errno.h>  #include <ouroboros/list.h>  #include <ouroboros/utils.h> @@ -32,12 +33,10 @@  #include <ouroboros/ipcp-dev.h>  #include <ouroboros/fcntl.h>  #include <ouroboros/fqueue.h> - -#define OUROBOROS_PREFIX "ipcpd/shim-eth-llc" -  #include <ouroboros/logs.h>  #include "ipcp.h" +#include "shim_eth_llc_messages.pb-c.h"  #include <net/if.h>  #include <signal.h> @@ -65,8 +64,6 @@  #include <poll.h>  #include <sys/mman.h> -#include "shim_eth_llc_messages.pb-c.h" -  typedef ShimEthLlcMsg shim_eth_llc_msg_t;  #define THIS_TYPE IPCP_SHIM_ETH_LLC @@ -80,6 +77,7 @@ typedef ShimEthLlcMsg shim_eth_llc_msg_t;                          + SHIM_ETH_LLC_MAX_SDU_SIZE)  #define EVENT_WAIT_TIMEOUT 100 /* us */ +#define NAME_QUERY_TIMEOUT 100000000 /* ns */  /* global for trapping signal */  int irmd_api; @@ -313,6 +311,7 @@ static int eth_llc_ipcp_sap_alloc(uint8_t * dst_addr,          shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT;          msg.code        = SHIM_ETH_LLC_MSG_CODE__FLOW_REQ; +        msg.has_ssap    = true;          msg.ssap        = ssap;          msg.dst_name    = dst_name;          msg.src_ae_name = src_ae_name; @@ -328,6 +327,7 @@ static int eth_llc_ipcp_sap_alloc_resp(uint8_t * dst_addr,          shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT;          msg.code         = SHIM_ETH_LLC_MSG_CODE__FLOW_REPLY; +        msg.has_ssap     = true;          msg.ssap         = ssap;          msg.has_dsap     = true;          msg.dsap         = dsap; @@ -341,8 +341,9 @@ static int eth_llc_ipcp_sap_dealloc(uint8_t * dst_addr, uint8_t ssap)  {          shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT; -        msg.code = SHIM_ETH_LLC_MSG_CODE__FLOW_DEALLOC; -        msg.ssap = ssap; +        msg.code     = SHIM_ETH_LLC_MSG_CODE__FLOW_DEALLOC; +        msg.has_ssap = true; +        msg.ssap     = ssap;          return eth_llc_ipcp_send_mgmt_frame(&msg, dst_addr);  } @@ -438,6 +439,42 @@ static int eth_llc_ipcp_flow_dealloc_req(uint8_t ssap)          return 0;  } +static int eth_llc_ipcp_name_query_req(char * name, uint8_t * r_addr) +{ +        shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT; + +        if (ipcp_data_reg_has(ipcpi.data, name)) { +                msg.code     = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REPLY; +                msg.dst_name = name; + +                eth_llc_ipcp_send_mgmt_frame(&msg, r_addr); +        } + +        return 0; +} + +static int eth_llc_ipcp_name_query_reply(char * name, uint8_t * r_addr) +{ +        uint64_t address = 0; +        struct list_head * pos; + +        memcpy(&address, r_addr, MAC_SIZE); + +        ipcp_data_dir_add_entry(ipcpi.data, name, address); + +        pthread_mutex_lock(&ipcpi.data->dir_queries_lock); +        list_for_each(pos, &ipcpi.data->dir_queries) { +                struct dir_query * e = +                        list_entry(pos, struct dir_query, next); +                if (strcmp(e->name, name) == 0) { +                        ipcp_data_dir_query_respond(e); +                } +        } +        pthread_mutex_unlock(&ipcpi.data->dir_queries_lock); + +        return 0; +} +  static int eth_llc_ipcp_mgmt_frame(uint8_t * buf, size_t len, uint8_t * r_addr)  {          shim_eth_llc_msg_t * msg = shim_eth_llc_msg__unpack(NULL, len, buf); @@ -448,7 +485,7 @@ static int eth_llc_ipcp_mgmt_frame(uint8_t * buf, size_t len, uint8_t * r_addr)          switch (msg->code) {          case SHIM_ETH_LLC_MSG_CODE__FLOW_REQ: -                if (ipcp_data_is_in_registry(ipcpi.data, msg->dst_name)) { +                if (ipcp_data_reg_has(ipcpi.data, msg->dst_name)) {                          eth_llc_ipcp_sap_req(msg->ssap,                                               r_addr,                                               msg->dst_name, @@ -464,6 +501,12 @@ static int eth_llc_ipcp_mgmt_frame(uint8_t * buf, size_t len, uint8_t * r_addr)          case SHIM_ETH_LLC_MSG_CODE__FLOW_DEALLOC:                  eth_llc_ipcp_flow_dealloc_req(msg->ssap);                  break; +        case SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REQ: +                eth_llc_ipcp_name_query_req(msg->dst_name, r_addr); +                break; +        case SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REPLY: +                eth_llc_ipcp_name_query_reply(msg->dst_name, r_addr); +                break;          default:                  LOG_ERR("Unknown message received %d.", msg->code);                  shim_eth_llc_msg__free_unpacked(msg, NULL); @@ -854,7 +897,7 @@ static int eth_llc_ipcp_name_reg(char * name)  {          pthread_rwlock_rdlock(&ipcpi.state_lock); -        if (ipcp_data_add_reg_entry(ipcpi.data, name)) { +        if (ipcp_data_reg_add_entry(ipcpi.data, name)) {                  pthread_rwlock_unlock(&ipcpi.state_lock);                  LOG_ERR("Failed to add %s to local registry.", name);                  return -1; @@ -871,13 +914,49 @@ static int eth_llc_ipcp_name_unreg(char * name)  {          pthread_rwlock_rdlock(&ipcpi.state_lock); -        ipcp_data_del_reg_entry(ipcpi.data, name); +        ipcp_data_reg_del_entry(ipcpi.data, name);          pthread_rwlock_unlock(&ipcpi.state_lock);          return 0;  } +static int eth_llc_ipcp_name_query(char * name) +{ +        uint8_t r_addr[MAC_SIZE]; +        struct timespec timeout = {0, NAME_QUERY_TIMEOUT}; +        shim_eth_llc_msg_t msg = SHIM_ETH_LLC_MSG__INIT; +        struct dir_query * query; +        int ret; + +        if (ipcp_data_dir_has(ipcpi.data, name)) +                return 0; + +        msg.code     = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REQ; +        msg.dst_name = name; + +        memset(r_addr, 0xff, MAC_SIZE); + +        query = ipcp_data_dir_query_create(name); +        if (query == NULL) +                return -1; + +        pthread_mutex_lock(&ipcpi.data->dir_queries_lock); +        list_add(&query->next, &ipcpi.data->dir_queries); +        pthread_mutex_unlock(&ipcpi.data->dir_queries_lock); + +        eth_llc_ipcp_send_mgmt_frame(&msg, r_addr); + +        ret = ipcp_data_dir_query_wait(query, &timeout); + +        pthread_mutex_lock(&ipcpi.data->dir_queries_lock); +        list_del(&query->next); +        ipcp_data_dir_query_destroy(query); +        pthread_mutex_unlock(&ipcpi.data->dir_queries_lock); + +        return ret; +} +  static int eth_llc_ipcp_flow_alloc(int           fd,                                     char *        dst_name,                                     char *        src_ae_name, @@ -885,6 +964,7 @@ static int eth_llc_ipcp_flow_alloc(int           fd,  {          uint8_t ssap = 0;          uint8_t r_addr[MAC_SIZE]; +        uint64_t addr = 0;          LOG_DBG("Allocating flow to %s.", dst_name); @@ -902,6 +982,13 @@ static int eth_llc_ipcp_flow_alloc(int           fd,                  return -1; /* -ENOTENROLLED */          } +        if (!ipcp_data_dir_has(ipcpi.data, dst_name)) { +                pthread_rwlock_unlock(&ipcpi.state_lock); +                LOG_ERR("Destination unreachable."); +                return -1; +        } +        addr = ipcp_data_dir_get_addr(ipcpi.data, dst_name); +          pthread_rwlock_wrlock(ð_llc_data.flows_lock);          ssap =  bmp_allocate(eth_llc_data.saps); @@ -917,7 +1004,7 @@ static int eth_llc_ipcp_flow_alloc(int           fd,          pthread_rwlock_unlock(ð_llc_data.flows_lock);          pthread_rwlock_unlock(&ipcpi.state_lock); -        memset(r_addr, 0xff, MAC_SIZE); +        memcpy(r_addr, &addr, MAC_SIZE);          if (eth_llc_ipcp_sap_alloc(r_addr,                                     ssap, @@ -1025,6 +1112,7 @@ static struct ipcp_ops eth_llc_ops = {          .ipcp_enroll          = NULL,          .ipcp_name_reg        = eth_llc_ipcp_name_reg,          .ipcp_name_unreg      = eth_llc_ipcp_name_unreg, +        .ipcp_name_query      = eth_llc_ipcp_name_query,          .ipcp_flow_alloc      = eth_llc_ipcp_flow_alloc,          .ipcp_flow_alloc_resp = eth_llc_ipcp_flow_alloc_resp,          .ipcp_flow_dealloc    = eth_llc_ipcp_flow_dealloc diff --git a/src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto b/src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto index 0e8a1ce2..4d027d98 100644 --- a/src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto +++ b/src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto @@ -1,14 +1,16 @@  enum shim_eth_llc_msg_code { -        FLOW_REQ     = 1; -        FLOW_REPLY   = 2; -        FLOW_DEALLOC = 3; +        FLOW_REQ         = 1; +        FLOW_REPLY       = 2; +        FLOW_DEALLOC     = 3; +        NAME_QUERY_REQ   = 4; +        NAME_QUERY_REPLY = 5;  };  message shim_eth_llc_msg {          required shim_eth_llc_msg_code code  = 1;          optional string dst_name             = 2;          optional string src_ae_name          = 3; -        required uint32 ssap                 = 4; +        optional uint32 ssap                 = 4;          optional uint32 dsap                 = 5;          optional sint32 response             = 6;  }; | 
