[lldp-devel] [PATCH 4/4] vdpnl use new netlink interface

Thomas Richter tmricht at linux.vnet.ibm.com
Mon Feb 25 15:36:05 UTC 2013


Use the new functions to decode netlink messages and for
the data to the vdp protocol.
Also use the new functions to forward switch originated
messages to libvirtd.
Add new functions to use the vdpnl_vsi data structure and
create vsi profile. Also create vdpnl_vsi data structures
from vsi profile data for transmission.

Signed-off-by: Thomas Richter <tmricht at linux.vnet.ibm.com>
---
 Makefile.am        |    3 +-
 event_iface.c      |  775 ++--------------------------------------------------
 include/lldp_vdp.h |    1 -
 lldp_vdp.c         |  187 +++++++++++++-
 4 files changed, 217 insertions(+), 749 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 8a6cf0d..f0b39e1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -66,7 +66,8 @@ lldp_8023.c include/lldp_8023.h \
 lldp_8021qaz.c include/lldp_8021qaz.h \
 lldp_8021qaz_cmds.c include/lldp_8021qaz_cmds.h \
 include/lldp_evb22.h qbg/lldp_evb22.c qbg/lldp_evb22_cmds.c \
-include/lldp_qbg22.h include/lldp_ecp22.h qbg/lldp_ecp22.c
+include/lldp_qbg22.h include/lldp_ecp22.h qbg/lldp_ecp22.c \
+qbg/lldp_vdpnl.c
 
 lib_LTLIBRARIES = liblldp_clif.la
 liblldp_clif_la_LDFLAGS = -version-info 1:0:0
diff --git a/event_iface.c b/event_iface.c
index 24ff486..c9879c7 100644
--- a/event_iface.c
+++ b/event_iface.c
@@ -59,47 +59,14 @@
 #include "lldp/states.h"
 #include "messages.h"
 #include "lldp_rtnl.h"
-#include "lldp_vdp.h"
+#include "lldp_vdpnl.h"
 #include "lldp_tlv.h"
 
-#define MAX_PAYLOAD 4096 /* maximum payload size */
-
-#define LIST_FOREACH_SAFE(pos, var, head, field)                        \
-	for ((var) = ((head)->lh_first), pos = ((var)->field.le_next);  \
-	     (var);                                                     \
-	     (var = pos), pos = (!pos) ? NULL : ((pos)->field.le_next))
-
 extern unsigned int if_nametoindex(const char *);
 extern char *if_indextoname(unsigned int, char *);
 
 static int peer_sock;
 
-static struct nla_policy ifla_vf_policy[IFLA_VF_MAX + 1] =
-{
-	[IFLA_VF_MAC] = { .minlen = sizeof(struct ifla_vf_mac),
-			  .maxlen = sizeof(struct ifla_vf_mac)},
-	[IFLA_VF_VLAN] = { .minlen = sizeof(struct ifla_vf_vlan),
-			   .maxlen = sizeof(struct ifla_vf_vlan)},
-};
-
-static struct nla_policy ifla_vf_ports_policy[IFLA_VF_PORT_MAX + 1] =
-{
-	[IFLA_VF_PORT] = { .type = NLA_NESTED },
-};
-
-static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] =
-{
-	[IFLA_PORT_VF]            = { .type = NLA_U32 },
-	[IFLA_PORT_PROFILE]       = { .type = NLA_STRING },
-	[IFLA_PORT_VSI_TYPE]      = { .minlen = sizeof(struct ifla_port_vsi) },
-	[IFLA_PORT_INSTANCE_UUID] = { .minlen = PORT_UUID_MAX,
-				      .maxlen = PORT_UUID_MAX, },
-	[IFLA_PORT_HOST_UUID]     = { .minlen = PORT_UUID_MAX,
-				      .maxlen = PORT_UUID_MAX, },
-	[IFLA_PORT_REQUEST]       = { .type = NLA_U8  },
-	[IFLA_PORT_RESPONSE]      = { .type = NLA_U16 },
-};
-
 static void event_if_decode_rta(int type, struct rtattr *rta, int *ls, char *d)
 {
 	switch (type) {
@@ -351,736 +318,52 @@ static void event_if_process_recvmsg(struct nlmsghdr *nlmsg)
 		NLMSG_PAYLOAD(nlmsg, 0));
 }
 
-static int event_if_parse_getmsg(struct nlmsghdr *nlh, int *ifindex)
-{
-	struct nlattr *tb[IFLA_MAX+1];
-	struct ifinfomsg *ifinfo;
-	char *ifname;
-
-	if (nlmsg_parse(nlh, sizeof(struct ifinfomsg),
-			(struct nlattr **)&tb, IFLA_MAX, NULL)) {
-		LLDPAD_ERR("Error parsing GETLINK request...\n");
-		return -EINVAL;
-	}
-
-	ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh);
-	*ifindex = ifinfo->ifi_index;
-	LLDPAD_DBG("interface index: %d\n", ifinfo->ifi_index);
-
-	if (tb[IFLA_IFNAME]) {
-		int myindex;
-
-		ifname = (char *)RTA_DATA(tb[IFLA_IFNAME]);
-		myindex = if_nametoindex(ifname);
-		LLDPAD_DBG("IFLA_IFNAME=%s myindex:%d\n", ifname, myindex);
-		if (*ifindex == 0)
-			*ifindex = myindex;
-		else if (*ifindex != myindex) {
-			LLDPAD_DBG("%s ifindex %d and myindex %d mismatch\n",
-				   __func__, *ifindex, myindex);
-			return -EINVAL;
-		}
-	}
-	return 0;
-}
-
-static int event_if_parse_setmsg(struct nlmsghdr *nlh)
-{
-	struct nlattr *tb[IFLA_MAX+1],
-		      *tb3[IFLA_PORT_MAX+1],
-		      *tb_vfinfo[IFLA_VF_MAX+1],
-		      *tb_vfinfo_list;
-	struct vsi_profile *profile, *p;
-	struct mac_vlan *mac_vlan = 0;
-	struct ifinfomsg *ifinfo;
-	struct vdp_data *vd;
-	char ifname[IFNAMSIZ];
-	int rem;
-	int ret = 0;
-
-	if (nlmsg_parse(nlh, sizeof(struct ifinfomsg),
-			(struct nlattr **)&tb, IFLA_MAX, NULL)) {
-		LLDPAD_ERR("Error parsing request...\n");
-		return -EINVAL;
-	}
-
-	LLDPAD_DBG("%s(%d): nlmsg_len %i\n", __FILE__, __LINE__, nlh->nlmsg_len);
-
-	if (tb[IFLA_IFNAME]) {
-		strncpy(ifname, (char *)RTA_DATA(tb[IFLA_IFNAME]), IFNAMSIZ);
-	} else {
-		ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh);
-		LLDPAD_DBG("interface index: %d\n", ifinfo->ifi_index);
-		if (!if_indextoname(ifinfo->ifi_index, ifname)) {
-			LLDPAD_ERR("Could not find name for interface %i !\n", ifinfo->ifi_index);
-			return -ENXIO;
-		}
-	}
-
-	LLDPAD_DBG("IFLA_IFNAME=%s\n", ifname);
-
-	vd = vdp_data(ifname);
-	if (!vd) {
-		LLDPAD_ERR("interface %s has not yet been configured !\n", ifname);
-		return -ENXIO;
-	}
-	if (!vd->vdpbit_on) {
-		LLDPAD_ERR("interface %s has VDP disabled!\n", ifname);
-		return -ENXIO;
-	}
-
-	if (!tb[IFLA_VFINFO_LIST]) {
-		LLDPAD_ERR("IFLA_VFINFO_LIST missing.\n");
-		return -EINVAL;
-	} else {
-		LLDPAD_DBG("FOUND IFLA_VFINFO_LIST!\n");
-	}
-
-	nla_for_each_nested(tb_vfinfo_list, tb[IFLA_VFINFO_LIST], rem) {
-		if (nla_type(tb_vfinfo_list) != IFLA_VF_INFO) {
-			LLDPAD_ERR("nested parsing of IFLA_VFINFO_LIST failed.\n");
-			return -EINVAL;
-		}
-
-		if (nla_parse_nested(tb_vfinfo, IFLA_VF_MAX, tb_vfinfo_list,
-				     ifla_vf_policy)) {
-			LLDPAD_ERR("nested parsing of IFLA_VF_INFO failed.\n");
-			return -EINVAL;
-		}
-	}
-
-	profile = vdp_alloc_profile();
-	if (!profile)
-		return -ENOMEM;
-
-	if (tb_vfinfo[IFLA_VF_MAC]) {
-		struct ifla_vf_mac *mac = RTA_DATA(tb_vfinfo[IFLA_VF_MAC]);
-		u8 *m = mac->mac;
-		LLDPAD_DBG("IFLA_VF_MAC=%2x:%2x:%2x:%2x:%2x:%2x\n",
-			m[0], m[1], m[2], m[3], m[4], m[5]);
-		mac_vlan = malloc(sizeof(struct mac_vlan));
-		if (!mac_vlan) {
-			ret = -ENOMEM;
-			goto out_err;
-		}
-		memset(mac_vlan, 0, sizeof(struct mac_vlan));
-		memcpy(&mac_vlan->mac, m, ETH_ALEN);
-	}
-
-	if (tb_vfinfo[IFLA_VF_VLAN]) {
-		struct ifla_vf_vlan *vlan = RTA_DATA(tb_vfinfo[IFLA_VF_VLAN]);
-		LLDPAD_DBG("IFLA_VF_VLAN=%d\n", vlan->vlan);
-		if (!mac_vlan) {
-			ret = -ENOMEM;
-			goto out_err;
-		}
-		mac_vlan->vlan = (u16) vlan->vlan;
-		mac_vlan->qos = (u8) vlan->qos;
-		mac_vlan->req_pid = (pid_t) nlh->nlmsg_pid;
-		mac_vlan->req_seq = (u32) nlh->nlmsg_seq;
-	}
-
-	LIST_INSERT_HEAD(&profile->macvid_head, mac_vlan, entry);
-	profile->entries++;
-
-	if (tb[IFLA_VF_PORTS]) {
-		struct nlattr *tb_vf_ports;
-
-		LLDPAD_DBG("FOUND IFLA_VF_PORTS\n");
-
-		nla_for_each_nested(tb_vf_ports, tb[IFLA_VF_PORTS], rem) {
-
-			LLDPAD_DBG("ITERATING\n");
-
-			if (nla_type(tb_vf_ports) != IFLA_VF_PORT) {
-				LLDPAD_DBG("not a IFLA_VF_PORT. skipping\n");
-				continue;
-			}
-
-			if (nla_parse_nested(tb3, IFLA_PORT_MAX, tb_vf_ports,
-					     ifla_port_policy)) {
-				LLDPAD_ERR("nested parsing on level 2 failed.\n");
-				ret = -EINVAL;
-				goto out_err;
-			}
-
-			if (tb3[IFLA_PORT_VF]) {
-				LLDPAD_DBG("IFLA_PORT_VF=%d\n", *(uint32_t*)(RTA_DATA(tb3[IFLA_PORT_VF])));
-			}
-
-			if (tb3[IFLA_PORT_PROFILE]) {
-				LLDPAD_DBG("IFLA_PORT_PROFILE=%s\n", (char *)RTA_DATA(tb3[IFLA_PORT_PROFILE]));
-			}
-
-			if (tb3[IFLA_PORT_VSI_TYPE]) {
-				struct ifla_port_vsi *pvsi;
-				int tid = 0;
-
-				pvsi = (struct ifla_port_vsi*)RTA_DATA(tb3[IFLA_PORT_VSI_TYPE]);
-				tid = pvsi->vsi_type_id[2] << 16 |
-					pvsi->vsi_type_id[1] << 8 |
-					pvsi->vsi_type_id[0];
-
-				LLDPAD_DBG("mgr_id : %d\n", pvsi->vsi_mgr_id);
-				LLDPAD_DBG("type_id : %d\n", tid);
-				LLDPAD_DBG("type_version : %d\n", pvsi->vsi_type_version);
-
-				profile->mgrid = pvsi->vsi_mgr_id;
-				profile->id = tid;
-				profile->version = pvsi->vsi_type_version;
-			}
-
-			if (tb3[IFLA_PORT_INSTANCE_UUID]) {
-				unsigned char *uuid;
-				uuid = (unsigned char *)RTA_DATA(tb3[IFLA_PORT_INSTANCE_UUID]);
-
-				char instance[INSTANCE_STRLEN+2];
-				instance2str(uuid, instance, sizeof(instance));
-				LLDPAD_DBG("IFLA_PORT_INSTANCE_UUID=%s\n", instance);
-
-				memcpy(&profile->instance,
-				       RTA_DATA(tb3[IFLA_PORT_INSTANCE_UUID]), 16);
-			}
-
-			if (tb3[IFLA_PORT_REQUEST]) {
-				LLDPAD_DBG("IFLA_PORT_REQUEST=%d\n",
-					*(uint8_t*)RTA_DATA(tb3[IFLA_PORT_REQUEST]));
-					profile->mode = *(uint8_t*)RTA_DATA(tb3[IFLA_PORT_REQUEST]);
-			}
-
-			if (tb3[IFLA_PORT_RESPONSE]) {
-				LLDPAD_DBG("IFLA_PORT_RESPONSE=%d\n",
-					*(uint16_t*)RTA_DATA(tb3[IFLA_PORT_RESPONSE]));
-				profile->response = *(uint16_t*)RTA_DATA(tb3[IFLA_PORT_RESPONSE]);
-			}
-		}
-	}
-
-	struct port *port = port_find_by_name(ifname);
-
-	if (port) {
-		profile->port = port;
-	} else {
-		LLDPAD_ERR("%s(%i): Could not find port for %s\n", __func__,
-		       __LINE__, ifname);
-		ret = -EEXIST;
-		goto out_err;
-	}
-
-	/* If the link is down, reject request */
-	if ((!port->portEnabled) && (profile->mode != VDP_MODE_DEASSOCIATE)) {
-		LLDPAD_WARN("%s(%i): Unable to associate, port %s not enabled !\n", __func__,
-		       __LINE__, ifname);
-		ret = -ENXIO;
-		goto out_err;
-	}
-
-	p = vdp_add_profile(NULL, profile);
-
-	if (!p)
-		goto out_err;
-
-	p->no_nlmsg = 1;
-	p->txmit = false;
-	vdp_trace_profile(p);
-	if (p != profile)
-		goto out_err;
-
-	return ret;
-
-out_err:
-	vdp_delete_profile(profile);
-	return ret;
-}
-
-static void event_if_parseResponseMsg(struct nlmsghdr *nlh)
+int event_trigger(struct nlmsghdr *nlh, pid_t pid)
 {
-	struct nlattr *tb[IFLA_MAX+1],
-		      *tb2[IFLA_VF_PORT_MAX + 1],
-		      *tb3[IFLA_PORT_MAX+1];
-
-	if (nlmsg_parse(nlh, sizeof(struct ifinfomsg),
-			(struct nlattr **)&tb, IFLA_MAX, NULL)) {
-		LLDPAD_ERR("Error parsing netlink response...\n");
-		return;
-	}
-
-	if (tb[IFLA_IFNAME]) {
-		LLDPAD_DBG("IFLA_IFNAME=%s\n", (char *)RTA_DATA(tb[IFLA_IFNAME]));
-	} else {
-		struct ifinfomsg *ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh);
-		LLDPAD_DBG("interface index: %d\n", ifinfo->ifi_index);
-	}
-
-	if (tb[IFLA_VF_PORTS]) {
-			if (nla_parse_nested(tb2, IFLA_VF_PORT_MAX, tb[IFLA_VF_PORTS],
-					     ifla_vf_ports_policy)) {
-				LLDPAD_ERR("nested parsing on level 1 failed.\n");
-				return;
-			}
-
-	        if (tb2[IFLA_VF_PORT]) {
-			if (nla_parse_nested(tb3, IFLA_PORT_MAX, tb2[IFLA_VF_PORT],
-					     ifla_port_policy)) {
-				LLDPAD_ERR("nested parsing on level 2 failed.\n");
-				return;
-			}
-
-			if (tb3[IFLA_PORT_VF]) {
-				LLDPAD_DBG("IFLA_PORT_VF=%d\n", *(uint32_t*)(RTA_DATA(tb3[IFLA_PORT_VF])));
-			}
-
-			if (tb3[IFLA_PORT_PROFILE]) {
-				LLDPAD_DBG("IFLA_PORT_PROFILE=%s\n", (char *)RTA_DATA(tb3[IFLA_PORT_PROFILE]));
-			}
-
-			if (tb3[IFLA_PORT_VSI_TYPE]) {
-				struct ifla_port_vsi *pvsi;
-				int tid = 0;
-				pvsi = (struct ifla_port_vsi*)RTA_DATA(tb3[IFLA_PORT_VSI_TYPE]);
-				tid = pvsi->vsi_type_id[2] << 16 |
-					pvsi->vsi_type_id[1] << 8 |
-					pvsi->vsi_type_id[0];
-				LLDPAD_DBG("mgr_id : %d "
-					"type_id : %d "
-					"type_version : %d\n",
-					pvsi->vsi_mgr_id,
-					tid,
-					pvsi->vsi_type_version);
-			}
-
-			if (tb3[IFLA_PORT_INSTANCE_UUID]) {
-				unsigned char *uuid;
-				uuid = (unsigned char *)RTA_DATA(tb3[IFLA_PORT_INSTANCE_UUID]);
-
-				char instance[INSTANCE_STRLEN+2];
-				instance2str(uuid, instance, sizeof(instance));
-				LLDPAD_DBG("IFLA_PORT_INSTANCE_UUID=%s\n", &instance[0]);
-			}
-
-			if (tb3[IFLA_PORT_REQUEST]) {
-				LLDPAD_DBG("IFLA_PORT_REQUEST=%d\n",
-					*(uint8_t*)RTA_DATA(tb3[IFLA_PORT_REQUEST]));
-			}
-			if (tb3[IFLA_PORT_RESPONSE]) {
-				LLDPAD_DBG("IFLA_PORT_RESPONSE=%d\n",
-					*(uint16_t*)RTA_DATA(tb3[IFLA_PORT_RESPONSE]));
-			}
-		}
-	}
-}
-
-struct nl_msg *event_if_constructResponse(int ifindex, struct nlmsghdr *from)
-{
-	struct nl_msg *nl_msg;
-	struct nlattr *vf_ports = NULL, *vf_port;
-	struct ifinfomsg ifinfo;
-	struct vdp_data *vd;
-	char ifname[IFNAMSIZ];
-	struct vsi_profile *p, *s;
-
-	if (!if_indextoname(ifindex, ifname)) {
-		LLDPAD_ERR("%s(%i): No name found for iface with index %i!\n",
-			   __func__, __LINE__, ifindex);
-		return NULL;
-	}
-
-	vd = vdp_data(ifname);
-	if (!vd) {
-		LLDPAD_ERR("%s(%i): Could not find vdp_data for %s!\n",
-			   __func__, __LINE__, ifname);
-		return NULL;
-	}
-
-	nl_msg = nlmsg_alloc();
-
-	if (!nl_msg) {
-		LLDPAD_ERR("%s(%i): Unable to allocate netlink message!\n",
-			   __func__, __LINE__);
-		return NULL;
-	}
-
-	if (nlmsg_put(nl_msg, from->nlmsg_pid, from->nlmsg_seq, NLMSG_DONE, 0, 0) == NULL)
-		goto err_exit;
-
-	ifinfo.ifi_index = ifindex;
-
-	if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
-		goto err_exit;
-
-	vf_ports = nla_nest_start(nl_msg, IFLA_VF_PORTS);
-
-	if (!vf_ports)
-		goto err_exit;
-
-	/* loop over all existing profiles on this interface and
-	 * put them into the nested IFLA_VF_PORT structure */
-	LIST_FOREACH_SAFE(s, p, &vd->profile_head, profile) {
-		if (p) {
-			vdp_trace_profile(p);
-
-			vf_port  = nla_nest_start(nl_msg, IFLA_VF_PORT);
-
-			if (!vf_port)
-				goto err_exit;
-
-			if (nla_put(nl_msg, IFLA_PORT_INSTANCE_UUID, 16, p->instance) < 0)
-				goto err_exit;
-
-			if (nla_put_u32(nl_msg, IFLA_PORT_VF, PORT_SELF_VF) < 0)
-				goto err_exit;
-
-			if (p->response != VDP_RESPONSE_NO_RESPONSE) {
-				if (nla_put_u16(nl_msg, IFLA_PORT_RESPONSE,
-						p->response) < 0)
-					goto err_exit;
-				if (p->state == VSI_EXIT)
-					vdp_remove_profile(p);
-			}
-
-			nla_nest_end(nl_msg, vf_port);
-		}
-	}
-
-	if (vf_ports)
-		nla_nest_end(nl_msg, vf_ports);
-
-	return nl_msg;
-
-err_exit:
-	nlmsg_free(nl_msg);
-
-	return NULL;
-}
-
-/*
- * Add one entry in the list of MAC,VLAN pairs.
- */
-static int add_pair(struct mac_vlan *mymac, struct nl_msg *nl_msg)
-{
-	struct nlattr *vfinfo;
-	struct ifla_vf_mac ifla_vf_mac = {
-		.vf = PORT_SELF_VF,
-		.mac = { 0, }
-	};
-	struct ifla_vf_vlan ifla_vf_vlan = {
-		.vf = PORT_SELF_VF,
-		.vlan = mymac->vlan,
-		.qos = mymac->qos
-	};
-
-
-	vfinfo = nla_nest_start(nl_msg, IFLA_VF_INFO);
-	if (!vfinfo)
-		return -1;
-
-	memcpy(ifla_vf_mac.mac, mymac->mac, ETH_ALEN);
-
-	if (nla_put(nl_msg, IFLA_VF_MAC, sizeof ifla_vf_mac, &ifla_vf_mac) < 0)
-		return -1;
-
-	if (nla_put(nl_msg, IFLA_VF_VLAN, sizeof ifla_vf_vlan, &ifla_vf_vlan)
-			< 0)
-		return -1;
-	nla_nest_end(nl_msg, vfinfo);
-	return 0;
-}
-
-/*
- * Walk along the MAC,VLAN ID list and add each entry into the message.
- */
-static int add_mac_vlan(struct vsi_profile *profile, struct nl_msg *nl_msg)
-{
-	struct nlattr *vfinfolist;
-	int cnt = 0;
-	struct mac_vlan *mv1;
-
-	vfinfolist = nla_nest_start(nl_msg, IFLA_VFINFO_LIST);
-	if (!vfinfolist)
-		return -1;
-	LIST_FOREACH(mv1, &profile->macvid_head, entry) {
-		if (add_pair(mv1, nl_msg) == 0)
-			++cnt;
-		else
-			break;
-	}
-	nla_nest_end(nl_msg, vfinfolist);
-	LLDPAD_DBG("%s: added pairs:%d\n", __func__, cnt);
-	return 0;
-}
-
-/* event_if_indicate_profile - indicate the status of a profile via netlink
- * @profile: pointer to the profile to indicate
- *
- * 0 on success, < 0 on error
- *
- * interface function to peer. Prepares a netlink message with the contents
- * of the current profile and sends it to peer via netlink.
- */
-int event_if_indicate_profile(struct vsi_profile *profile)
-{
-	struct nlmsghdr *nlh;
-	struct nl_msg *nl_msg;
-	struct nlattr *vf_ports = NULL, *vf_port;
-	struct ifinfomsg ifinfo;
-	struct msghdr msg;
 	struct sockaddr_nl dest_addr;
-	struct iovec iov;
-	struct vdp_data *vd;
-	char *ifname;
-	int result;
-	struct ifla_port_vsi portvsi;
-	struct mac_vlan *macp = 0;
-
-	LLDPAD_DBG("%s: no_nlmsg:%d\n", __func__, profile->no_nlmsg);
-	if (profile->no_nlmsg)
-		return 0;
-	if (LIST_EMPTY(&profile->macvid_head))
-		return 0;
-	macp = LIST_FIRST(&profile->macvid_head);
-	if (!macp->req_pid)
-		return 0;
-	sleep(1);		/* Delay message notification */
-	nl_msg = nlmsg_alloc();
-	if (!nl_msg) {
-		LLDPAD_ERR("%s: Unable to allocate netlink message\n",
-			   __func__);
-		return -ENOMEM;
-	}
-	if (!profile->port || !profile->port->ifname) {
-		LLDPAD_ERR("%s: No ifname found for profile %p:\n",
-			   __func__, profile);
-		vdp_trace_profile(profile);
-		goto err_exit;
-	}
-	ifname = profile->port->ifname;
-	vd = vdp_data(ifname);
-	if (!vd) {
-		LLDPAD_ERR("%s: Could not find vdp_data for %s !\n",
-			   __func__, ifname);
-		goto err_exit;
-	}
-	if (nlmsg_put(nl_msg, getpid(), macp->req_seq, NLMSG_DONE, 0, 0) == NULL)
-		goto err_exit;
-	ifinfo.ifi_index = if_nametoindex(ifname);
-	if (ifinfo.ifi_index == 0) {
-		LLDPAD_ERR("%s: Could not find index for ifname %s\n",
-			   __func__, ifname);
-		goto err_exit;
-	}
-	if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
-		goto err_exit;
-
-	if (nla_put_string(nl_msg, IFLA_IFNAME, ifname) < 0)
-		goto err_exit;
-
-	vdp_trace_profile(profile);
-
-	if (add_mac_vlan(profile, nl_msg))
-		goto err_exit;
-
-	portvsi.vsi_mgr_id = profile->mgrid;
-	portvsi.vsi_type_id[0] = profile->id & 0xff;
-	portvsi.vsi_type_id[1] = (profile->id >> 8) & 0xff;
-	portvsi.vsi_type_id[2] = (profile->id >> 16) & 0xff;
-	portvsi.vsi_type_version = profile->version;
-	vf_ports = nla_nest_start(nl_msg, IFLA_VF_PORTS);
-	if (!vf_ports)
-		goto err_exit;
-
-	vf_port = nla_nest_start(nl_msg, IFLA_VF_PORT);
-	if (!vf_port)
-		goto err_exit;
-	if (nla_put(nl_msg, IFLA_PORT_VSI_TYPE, sizeof portvsi,
-		&portvsi) < 0)
-		goto err_exit;
-	if (nla_put(nl_msg, IFLA_PORT_INSTANCE_UUID, 16, profile->instance) < 0)
-		goto err_exit;
-	if (nla_put_u32(nl_msg, IFLA_PORT_VF, PORT_SELF_VF) < 0)
-		goto err_exit;
-	if (nla_put_u16(nl_msg, IFLA_PORT_REQUEST, VDP_MODE_DEASSOCIATE) < 0)
-		goto err_exit;
-	nla_nest_end(nl_msg, vf_port);
-	if (vf_ports)
-		nla_nest_end(nl_msg, vf_ports);
-	memset(&dest_addr, 0, sizeof(dest_addr));
-	memset(&msg, 0, sizeof(msg));
+	int dest_addrlen = sizeof dest_addr, rc;
 
+	memset(&dest_addr, 0, dest_addrlen);
 	dest_addr.nl_family = AF_NETLINK;
-	dest_addr.nl_pid = macp->req_pid;
-
-	nlh = nlmsg_hdr(nl_msg);
-	nlh->nlmsg_type = RTM_SETLINK;
-
-	iov.iov_base = (void *)nlh;
-	iov.iov_len = nlh->nlmsg_len;
-
-	msg.msg_name = (void *)&dest_addr;
-	msg.msg_namelen = sizeof(dest_addr);
-	msg.msg_iov = &iov;
-	msg.msg_iovlen = 1;
-
-	LLDPAD_DBG("dest_addr.nl_pid: %d\n", dest_addr.nl_pid);
-	LLDPAD_DBG("nlh.nl_pid: %d\n", nlh->nlmsg_pid);
-	LLDPAD_DBG("nlh_type: %d\n", nlh->nlmsg_type);
-	LLDPAD_DBG("nlh_seq: 0x%x\n", nlh->nlmsg_seq);
-	LLDPAD_DBG("nlh_len: 0x%x\n", nlh->nlmsg_len);
-	result = sendmsg(peer_sock, &msg, 0);
-	LLDPAD_DBG("%s result:%d pid:%d sender-pid:%d\n",
-		   __func__, result, macp->req_pid, nlh->nlmsg_pid);
-	if (result < 0)
-		LLDPAD_ERR("%s error %i: (len:%u) send on netlink socket %i\n",
-			   __func__, errno, peer_sock, nlh->nlmsg_len);
-	else
-		LLDPAD_DBG("%s(%i): sent %d bytes !\n",
-			   __func__, __LINE__, result);
-	vdp_remove_profile(profile);
-	return 0;
-
-err_exit:
-	vdp_remove_profile(profile);
-	nlmsg_free(nl_msg);
-	return -EINVAL;
-}
-
-struct nl_msg *event_if_simpleResponse(int err, struct nlmsghdr *from)
-{
-	struct nl_msg *nl_msg = nlmsg_alloc();
-	struct nlmsgerr nlmsgerr;
-
-	memset(&nlmsgerr, 0x0, sizeof(nlmsgerr));
-
-	nlmsgerr.error = err;
-	LLDPAD_DBG("RESPONSE error code: %d\n",err);
+	dest_addr.nl_pid = pid;
 
-	if (nlmsg_put(nl_msg, from->nlmsg_pid, from->nlmsg_seq, NLMSG_ERROR, 0, 0) == NULL)
-		goto err_exit;
-
-	if (nlmsg_append(nl_msg, &nlmsgerr, sizeof(nlmsgerr), NLMSG_ALIGNTO) < 0)
-		goto err_exit;
-
-	return nl_msg;
-
-err_exit:
-	nlmsg_free(nl_msg);
-
-	return NULL;
+	rc = sendto(peer_sock, (void *)nlh, nlh->nlmsg_len, 0,
+			 (struct sockaddr *) &dest_addr, dest_addrlen);
+	LLDPAD_DBG("%s rc:%d pid:%d sender-pid:%d msgsize:%d\n",
+		   __func__, rc, pid, nlh->nlmsg_pid, nlh->nlmsg_len);
+	return rc;
 }
 
 static void
 event_iface_receive_user_space(int sock,
 			       UNUSED void *eloop_ctx, UNUSED void *sock_ctx)
 {
-	struct nlmsghdr *nlh, *nlh2;
-	struct nl_msg *nl_msg;
-	struct msghdr msg;
 	struct sockaddr_nl dest_addr;
-	struct iovec iov;
+	unsigned char buf[MAX_PAYLOAD];
+	socklen_t fromlen = sizeof(dest_addr);
 	int result;
-	int err;
-	int ifindex = 0;
-
-	nlh = (struct nlmsghdr *)calloc(1,
-					NLMSG_SPACE(MAX_PAYLOAD));
-	if (!nlh) {
-		LLDPAD_ERR("%s(%i): could not allocate nlh !\n", __func__,
-		       __LINE__);
-		return;
-	}
-	memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
-
-	memset(&dest_addr, 0, sizeof(dest_addr));
-	iov.iov_base = (void *)nlh;
-	iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
-	msg.msg_name = (void *)&dest_addr;
-	msg.msg_namelen = sizeof(dest_addr);
-	msg.msg_iov = &iov;
-	msg.msg_iovlen = 1;
-	msg.msg_control = NULL;
-	msg.msg_controllen = 0;
-	msg.msg_flags = 0;
 
 	LLDPAD_DBG("Waiting for message\n");
-	result = recvmsg(sock, &msg, MSG_DONTWAIT);
-
-	LLDPAD_DBG("%s(%i): ", __func__, __LINE__);
-	LLDPAD_DBG("recvmsg received %d bytes\n", result);
-
+	result = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
+		       (struct sockaddr *) &dest_addr, &fromlen);
 	if(result < 0) {
-		LLDPAD_ERR("Error receiving from netlink socket : %s\n", strerror(errno));
-	}
-
-	LLDPAD_DBG("dest_addr.nl_pid: %d\n", dest_addr.nl_pid);
-	LLDPAD_DBG("nlh.nl_pid: %d\n", nlh->nlmsg_pid);
-	LLDPAD_DBG("nlh_type: %d\n", nlh->nlmsg_type);
-	LLDPAD_DBG("nlh_seq: 0x%x\n", nlh->nlmsg_seq);
-	LLDPAD_DBG("nlh_len: 0x%x\n", nlh->nlmsg_len);
-
-
-	switch (nlh->nlmsg_type) {
-		case RTM_SETLINK:
-			LLDPAD_DBG("RTM_SETLINK\n");
-
-			err = event_if_parse_setmsg(nlh);
-
-			/* send simple response wether profile was accepted
-			 * or not */
-			nl_msg = event_if_simpleResponse(err, nlh);
-			nlh2 = nlmsg_hdr(nl_msg);
-			break;
-		case RTM_GETLINK:
-			LLDPAD_DBG("RTM_GETLINK\n");
-
-			err = event_if_parse_getmsg(nlh, &ifindex);
-			if (err) {
-				nl_msg = event_if_simpleResponse(err, nlh);
-				nlh2 = nlmsg_hdr(nl_msg);
-				break;
-			}
-
-			nl_msg = event_if_constructResponse(ifindex, nlh);
-			if (!nl_msg) {
-				LLDPAD_ERR("%s: Unable to construct response\n",
-				       __func__);
-				goto out_err;
-			}
-
-			nlh2 = nlmsg_hdr(nl_msg);
-
-			LLDPAD_DBG("RESPONSE:\n");
-
-			event_if_parseResponseMsg(nlh2);
-
-			break;
-
-		default:
-			LLDPAD_ERR("%s: Unknown type: %d\n",
-				   __func__, nlh->nlmsg_type);
-			goto out_err2;
+		LLDPAD_ERR("%s:receive error on netlink socket:%d\n", __func__,
+			    errno);
+		return;
 	}
-
-	iov.iov_base = (void *)nlh2;
-	iov.iov_len = nlh2->nlmsg_len;
-
-	msg.msg_name = (void *)&dest_addr;
-	msg.msg_namelen = sizeof(dest_addr);
-	msg.msg_iov = &iov;
-	msg.msg_iovlen = 1;
-
-	result = sendmsg(sock, &msg, 0);
-
-	if (result < 0) {
-		LLDPAD_ERR("Error sending on netlink socket (%s) !\n", strerror(errno));
-	} else {
-		LLDPAD_DBG("Sent %d bytes !\n", result);
+	LLDPAD_DBG("%s:recvfrom received %d bytes from pid %d\n", __func__,
+		   result, dest_addr.nl_pid);
+	result = vdpnl_recv(buf, sizeof buf);
+	if (result > 0) {		/* Data to send back */
+		result = sendto(sock, buf, result, 0,
+				(struct sockaddr *) &dest_addr, fromlen);
+		if (result < 0)
+			LLDPAD_ERR("%s:send error on netlink socket:%d\n",
+				   __func__, errno);
+		else
+			LLDPAD_DBG("%s:sentto pid %d bytes:%d\n", __func__,
+				   dest_addr.nl_pid, result);
 	}
-
-out_err:
-	nlmsg_free(nl_msg);
-out_err2:
-	free(nlh);
-
-	return;
 }
 
 static void
diff --git a/include/lldp_vdp.h b/include/lldp_vdp.h
index bbcde02..1ad5365 100644
--- a/include/lldp_vdp.h
+++ b/include/lldp_vdp.h
@@ -162,7 +162,6 @@ int vdp_vsis(char *);
 const char *vdp_response2str(int);
 void vdp_trace_profile(struct vsi_profile *);
 int instance2str(const u8 *, char *, size_t);
-int event_if_indicate_profile(struct vsi_profile *);
 struct vsi_profile *vdp_alloc_profile(void);
 void vdp_delete_profile(struct vsi_profile *);
 struct vsi_profile *vdp_find_profile(struct vdp_data *, struct vsi_profile *);
diff --git a/lldp_vdp.c b/lldp_vdp.c
index 92fd5bc..3c67b07 100644
--- a/lldp_vdp.c
+++ b/lldp_vdp.c
@@ -26,6 +26,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <net/if.h>
 #include <sys/queue.h>
 #include <sys/socket.h>
@@ -36,6 +37,7 @@
 #include <assert.h>
 #include "lldp.h"
 #include "lldp_vdp.h"
+#include "lldp_vdpnl.h"
 #include "eloop.h"
 #include "lldp_evb.h"
 #include "messages.h"
@@ -69,6 +71,7 @@ const char * const vsi_states[] = {
 
 int vdp_start_localchange_timer(struct vsi_profile *p);
 int vdp_remove_profile(struct vsi_profile *profile);
+int vdp_trigger(struct vsi_profile *profile);
 
 void vdp_trace_profile(struct vsi_profile *p)
 {
@@ -707,7 +710,7 @@ void vdp_vsi_sm_station(struct vsi_profile *profile)
 			if (bye)
 				vdp_remove_profile(profile);
 			else
-				event_if_indicate_profile(profile);
+				vdp_trigger(profile);
 			break;
 		default:
 			LLDPAD_ERR("%s: ERROR VSI state machine in invalid state %d\n",
@@ -1641,3 +1644,185 @@ void vdp_update(char *ifname, u8 ccap)
 			   vdp->vdpbit_on);
 	}
 }
+
+/*
+ * Handle a VSI request from buddy.
+ */
+int vdp_request(struct vdpnl_vsi *vsi)
+{
+	struct vdp_data *vd;
+	struct vsi_profile *profile, *p;
+	struct port *port = port_find_by_name(vsi->ifname);
+	struct mac_vlan *mac_vlan;
+	int ret = 0;
+
+	vd = vdp_data(vsi->ifname);
+	if (!vd) {
+		LLDPAD_ERR("%s: %s has not yet been configured\n", __func__,
+			   vsi->ifname);
+		return -ENXIO;
+	}
+	if (!vd->vdpbit_on) {
+		LLDPAD_ERR("%s: %s has VDP disabled\n", __func__, vsi->ifname);
+		return -ENXIO;
+	}
+
+	if (!port) {
+		LLDPAD_ERR("%s: %s can not find port\n", __func__, vsi->ifname);
+		return -ENODEV;
+	}
+	/* If the link is down, reject request */
+	if (!port->portEnabled && vsi->request != VDP_MODE_DEASSOCIATE) {
+		LLDPAD_WARN("%s: %s not enabled, unable to associate\n",
+			    __func__, vsi->ifname);
+		return -ENXIO;
+	}
+
+	profile = vdp_alloc_profile();
+	if (!profile)
+		return -ENOMEM;
+	mac_vlan = calloc(1, sizeof(struct mac_vlan));
+	if (!mac_vlan) {
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	profile->port = port;
+	memcpy(&mac_vlan->mac, vsi->maclist->mac, sizeof mac_vlan->mac);
+	mac_vlan->vlan = vsi->maclist->vlan;
+	mac_vlan->qos = vsi->maclist->qos;
+	mac_vlan->req_pid = vsi->req_pid;
+	mac_vlan->req_seq = vsi->req_seq;
+	LIST_INSERT_HEAD(&profile->macvid_head, mac_vlan, entry);
+	profile->entries = 1;
+
+	profile->mgrid = vsi->vsi_mgrid;
+	profile->id = vsi->vsi_typeid;
+	profile->version = vsi->vsi_typeversion;
+	profile->mode = vsi->request;
+	profile->response = vsi->response;
+	memcpy(profile->instance, vsi->vsi_uuid, sizeof vsi->vsi_uuid);
+	p = vdp_add_profile(vd, profile);
+	p->no_nlmsg = 1;
+	p->txmit = false;
+	vdp_trace_profile(p);
+	if (p != profile)
+		goto out_err;
+	return ret;
+
+out_err:
+	vdp_delete_profile(profile);
+	return ret;
+}
+
+/*
+ * Query a VSI request from buddy and report its progress. Use the interface
+ * name to determine the VSI profile list. Return one entry in parameter 'vsi'
+ * use the structure members response and vsi_uuid.
+ * Returns
+ * 1  valid VSI data returned
+ * 0  end of queue (no VSI data returned)
+ * <0 errno
+ */
+int vdp_status(int number, struct vdpnl_vsi *vsi)
+{
+	struct vdp_data *vd;
+	struct vsi_profile *p;
+	int i = 0, ret = 0;
+
+	vd = vdp_data(vsi->ifname);
+	if (!vd) {
+		LLDPAD_ERR("%s: %s has not yet been configured\n", __func__,
+			   vsi->ifname);
+		return -ENODEV;
+	}
+	/* Interate to queue element number */
+	LIST_FOREACH(p, &vd->profile_head, profile) {
+		if (++i == number) {
+			ret = 1;
+			break;
+		}
+	}
+	if (ret) {
+		vdp_trace_profile(p);
+		vsi->response = p->response;
+		memcpy(vsi->vsi_uuid, p->instance, sizeof vsi->vsi_uuid);
+		if (p->response != VDP_RESPONSE_NO_RESPONSE
+		    && p->state == VSI_EXIT)
+			vdp_remove_profile(p);
+	}
+	LLDPAD_DBG("%s: entry:%d more:%d\n", __func__, number, ret);
+	return ret;
+}
+
+/*
+ * Copy MAC-VLAN list from profile to vdpnl structure.
+ */
+static void copy_maclist(struct vsi_profile *p, struct vdpnl_mac *macp)
+{
+	struct mac_vlan *mv1;
+
+	LIST_FOREACH(mv1, &p->macvid_head, entry) {
+		macp->vlan = mv1->vlan;
+		macp->qos =  mv1->qos;
+		memcpy(macp->mac, mv1->mac, sizeof macp->mac);
+		++macp;
+	}
+}
+
+/*
+ * Prepare data for a netlink message to originator of VSI.
+ * Forward a notification from switch.
+ */
+int vdp_trigger(struct vsi_profile *profile)
+{
+	struct vdpnl_vsi vsi;
+	struct vdp_data *vd;
+	struct mac_vlan *macp = 0;
+	int rc = -EINVAL;
+	struct vdpnl_mac maclist[profile->entries];
+
+	vsi.macsz = profile->entries;
+	vsi.maclist = maclist;
+	LLDPAD_DBG("%s: no_nlmsg:%d\n", __func__, profile->no_nlmsg);
+	vdp_trace_profile(profile);
+	if (profile->no_nlmsg)
+		return 0;
+	if (LIST_EMPTY(&profile->macvid_head))
+		return 0;
+	macp = LIST_FIRST(&profile->macvid_head);
+	if (!macp->req_pid)
+		return 0;
+	sleep(1);		/* Delay message notification */
+	if (!profile->port || !profile->port->ifname) {
+		LLDPAD_ERR("%s: no ifname found for profile %p:\n", __func__,
+			   profile);
+		goto error_exit;
+	}
+	memcpy(vsi.ifname, profile->port->ifname, sizeof vsi.ifname);
+	vd = vdp_data(vsi.ifname);
+	if (!vd) {
+		LLDPAD_ERR("%s: %s could not find vdp_data\n", __func__,
+			   vsi.ifname);
+		goto error_exit;
+	}
+	vsi.ifindex = if_nametoindex(vsi.ifname);
+	if (vsi.ifindex == 0) {
+		LLDPAD_ERR("%s: %s could not find index for ifname\n",
+			   __func__, vsi.ifname);
+		goto error_exit;
+	}
+	vsi.macsz = profile->entries;
+	copy_maclist(profile, vsi.maclist);
+	vsi.req_pid = macp->req_pid;
+	vsi.req_seq = macp->req_seq;
+	vsi.vsi_mgrid = profile->mgrid;
+	vsi.vsi_typeid = profile->id;
+	vsi.vsi_typeversion = profile->version;
+	memcpy(vsi.vsi_uuid, profile->instance, sizeof vsi.vsi_uuid);
+	vsi.request = VDP_MODE_DEASSOCIATE;
+	rc = vdpnl_send(&vsi);
+error_exit:
+	vdp_remove_profile(profile);
+	return rc;
+}
-- 
1.7.1



More information about the lldp-devel mailing list