summaryrefslogtreecommitdiff
path: root/src/ipcpd/shim-eth-llc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipcpd/shim-eth-llc')
-rw-r--r--src/ipcpd/shim-eth-llc/main.c114
-rw-r--r--src/ipcpd/shim-eth-llc/shim_eth_llc_messages.proto10
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(&eth_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(&eth_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;
};