Blame lldp_8023.c

Packit 597cd4
/*******************************************************************************
Packit 597cd4
Packit 597cd4
  LLDP Agent Daemon (LLDPAD) Software
Packit 597cd4
  Copyright(c) 2007-2010 Intel Corporation.
Packit 597cd4
Packit 597cd4
  This program is free software; you can redistribute it and/or modify it
Packit 597cd4
  under the terms and conditions of the GNU General Public License,
Packit 597cd4
  version 2, as published by the Free Software Foundation.
Packit 597cd4
Packit 597cd4
  This program is distributed in the hope it will be useful, but WITHOUT
Packit 597cd4
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
Packit 597cd4
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
Packit 597cd4
  more details.
Packit 597cd4
Packit 597cd4
  You should have received a copy of the GNU General Public License along with
Packit 597cd4
  this program; if not, write to the Free Software Foundation, Inc.,
Packit 597cd4
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
Packit 597cd4
Packit 597cd4
  The full GNU General Public License is included in this distribution in
Packit 597cd4
  the file called "COPYING".
Packit 597cd4
Packit 597cd4
  Contact Information:
Packit 597cd4
  open-lldp Mailing List <lldp-devel@open-lldp.org>
Packit 597cd4
Packit 597cd4
*******************************************************************************/
Packit 597cd4
Packit 597cd4
#include <stdlib.h>
Packit 597cd4
#include <errno.h>
Packit 597cd4
#include <net/if.h>
Packit 597cd4
#include <sys/queue.h>
Packit 597cd4
#include <sys/socket.h>
Packit 597cd4
#include <sys/ioctl.h>
Packit 597cd4
#include <sys/utsname.h>
Packit 597cd4
#include <linux/if_bridge.h>
Packit 597cd4
#include "lldp.h"
Packit 597cd4
#include "lldp_8023.h"
Packit 597cd4
#include "messages.h"
Packit 597cd4
#include "config.h"
Packit 597cd4
#include "lldp_8023_clif.h"
Packit 597cd4
#include "lldp_8023_cmds.h"
Packit 597cd4
Packit 597cd4
extern struct lldp_head lldp_head;
Packit 597cd4
Packit 597cd4
struct tlv_info_8023_maccfg {
Packit 597cd4
	u8 oui[3];
Packit 597cd4
	u8 sub;
Packit 597cd4
	u8 neg;
Packit 597cd4
	u16 adv;
Packit 597cd4
	u16 mau;
Packit 597cd4
} __attribute__ ((__packed__));
Packit 597cd4
Packit 597cd4
struct tlv_info_8023_maxfs {
Packit 597cd4
	u8 oui[3];
Packit 597cd4
	u8 sub;
Packit 597cd4
	u16 mfs;
Packit 597cd4
} __attribute__ ((__packed__));
Packit 597cd4
Packit 597cd4
struct tlv_info_8023_linkagg {
Packit 597cd4
	u8 oui[3];
Packit 597cd4
	u8 sub;
Packit 597cd4
	u8 status;
Packit 597cd4
	u32 portid;
Packit 597cd4
} __attribute__ ((__packed__));
Packit 597cd4
Packit 597cd4
struct tlv_info_8023_powvmdi {
Packit 597cd4
	u8 oui[3];
Packit 597cd4
	u8 sub;
Packit 597cd4
	u8 caps;
Packit 597cd4
	u8 pairs;
Packit 597cd4
	u8 class;
Packit 597cd4
} __attribute__ ((__packed__));
Packit 597cd4
Packit 597cd4
static const struct lldp_mod_ops ieee8023_ops =  {
Packit 597cd4
	.lldp_mod_register	= ieee8023_register,
Packit 597cd4
	.lldp_mod_unregister	= ieee8023_unregister,
Packit 597cd4
	.lldp_mod_gettlv	= ieee8023_gettlv,
Packit 597cd4
	.lldp_mod_ifup		= ieee8023_ifup,
Packit 597cd4
	.lldp_mod_ifdown	= ieee8023_ifdown,
Packit 597cd4
	.get_arg_handler	= ieee8023_get_arg_handlers,
Packit 597cd4
};
Packit 597cd4
Packit 597cd4
static struct ieee8023_data *ieee8023_data(const char *ifname, enum agent_type type)
Packit 597cd4
{
Packit 597cd4
	struct ieee8023_user_data *ud;
Packit 597cd4
	struct ieee8023_data *bd = NULL;
Packit 597cd4
Packit 597cd4
	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8023);
Packit 597cd4
	if (ud) {
Packit 597cd4
		LIST_FOREACH(bd, &ud->head, entry) {
Packit 597cd4
			if (!strncmp(ifname, bd->ifname, IFNAMSIZ) &&
Packit 597cd4
			    (type == bd->agenttype))
Packit 597cd4
				return bd;
Packit 597cd4
		}
Packit 597cd4
	}
Packit 597cd4
	return NULL;
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
/*
Packit 597cd4
 * ieee8023_bld_maccfg_tlv - build the MAC/PHY Config Status TLV
Packit 597cd4
 * @bd: the med data struct
Packit 597cd4
 *
Packit 597cd4
 * Returns 0 on success
Packit 597cd4
 */
Packit 597cd4
static int ieee8023_bld_maccfg_tlv(struct ieee8023_data *bd,
Packit 597cd4
				   struct lldp_agent *agent)
Packit 597cd4
{
Packit 597cd4
	int rc = 0;
Packit 597cd4
	struct unpacked_tlv *tlv = NULL;
Packit 597cd4
	struct tlv_info_8023_maccfg maccfg;
Packit 597cd4
Packit 597cd4
	/* free old one if it exists */
Packit 597cd4
	FREE_UNPKD_TLV(bd, maccfg);
Packit 597cd4
Packit 597cd4
	/* mandatory for LLDP-MED */
Packit 597cd4
	if (!is_tlv_txenabled(bd->ifname, agent->type,
Packit 597cd4
			      TLVID_8023(LLDP_8023_MACPHY_CONFIG_STATUS))) {
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	/* load from config */
Packit 597cd4
	memset(&maccfg, 0, sizeof(maccfg));
Packit 597cd4
	if (get_config_tlvinfo_bin(bd->ifname, agent->type,
Packit 597cd4
				   TLVID_8023(LLDP_8023_MACPHY_CONFIG_STATUS),
Packit 597cd4
				   &maccfg, sizeof(maccfg))) {
Packit 597cd4
		hton24(maccfg.oui, OUI_IEEE_8023);
Packit 597cd4
		maccfg.sub = LLDP_8023_MACPHY_CONFIG_STATUS;
Packit 597cd4
		if (is_autoneg_supported(bd->ifname))
Packit 597cd4
			maccfg.neg |= LLDP_8023_MACPHY_AUTONEG_SUPPORT;
Packit 597cd4
		if (is_autoneg_enabled(bd->ifname))
Packit 597cd4
			maccfg.neg |= LLDP_8023_MACPHY_AUTONEG_ENABLED;
Packit 597cd4
		maccfg.adv = htons(get_maucaps(bd->ifname));
Packit 597cd4
		maccfg.mau = htons(get_mautype(bd->ifname));
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	tlv = create_tlv();
Packit 597cd4
	if (!tlv)
Packit 597cd4
		goto out_err;
Packit 597cd4
Packit 597cd4
	tlv->type = ORG_SPECIFIC_TLV;
Packit 597cd4
	tlv->length = sizeof(maccfg);
Packit 597cd4
	tlv->info = (u8 *)malloc(tlv->length);
Packit 597cd4
	if(!tlv->info) {
Packit 597cd4
		free(tlv);
Packit 597cd4
		tlv = NULL;
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
	memcpy(tlv->info, &maccfg, tlv->length);
Packit 597cd4
	bd->maccfg = tlv;
Packit 597cd4
	rc = 0;
Packit 597cd4
out_err:
Packit 597cd4
	return rc;
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
/*
Packit 597cd4
 * ieee8023_bld_maxfs_tlv - build the Max Frame Size TLV
Packit 597cd4
 * @bd: the med data struct
Packit 597cd4
 *
Packit 597cd4
 * Returns 0 on success
Packit 597cd4
 */
Packit 597cd4
static int ieee8023_bld_maxfs_tlv(struct ieee8023_data *bd,
Packit 597cd4
				  struct lldp_agent *agent)
Packit 597cd4
{
Packit 597cd4
	int rc = 0;
Packit 597cd4
	struct unpacked_tlv *tlv = NULL;
Packit 597cd4
	struct tlv_info_8023_maxfs maxfs;
Packit 597cd4
Packit 597cd4
	/* free old one if it exists */
Packit 597cd4
	FREE_UNPKD_TLV(bd, maxfs);
Packit 597cd4
Packit 597cd4
	if (!is_tlv_txenabled(bd->ifname, agent->type,
Packit 597cd4
			      TLVID_8023(LLDP_8023_MAXIMUM_FRAME_SIZE))) {
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	/* load from config */
Packit 597cd4
	memset(&maxfs, 0, sizeof(maxfs));
Packit 597cd4
	if (get_config_tlvinfo_bin(bd->ifname, agent->type,
Packit 597cd4
				   TLVID_8023(LLDP_8023_MAXIMUM_FRAME_SIZE),
Packit 597cd4
				   &maxfs, sizeof(maxfs))) {
Packit 597cd4
		hton24(maxfs.oui, OUI_IEEE_8023);
Packit 597cd4
		maxfs.sub = LLDP_8023_MAXIMUM_FRAME_SIZE;
Packit 597cd4
		maxfs.mfs = htons(get_mfs(bd->ifname));
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	tlv = create_tlv();
Packit 597cd4
	if (!tlv)
Packit 597cd4
		goto out_err;
Packit 597cd4
Packit 597cd4
	tlv->type = ORG_SPECIFIC_TLV;
Packit 597cd4
	tlv->length = sizeof(maxfs);
Packit 597cd4
	tlv->info = (u8 *)malloc(tlv->length);
Packit 597cd4
	if(!tlv->info) {
Packit 597cd4
		free(tlv);
Packit 597cd4
		tlv = NULL;
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
	memcpy(tlv->info, &maxfs, tlv->length);
Packit 597cd4
	bd->maxfs = tlv;
Packit 597cd4
	rc = 0;
Packit 597cd4
out_err:
Packit 597cd4
	return rc;
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
/*
Packit 597cd4
 * ieee8023_bld_linkagg_tlv - build the Link Aggregation TLV
Packit 597cd4
 * @bd: the med data struct
Packit 597cd4
 *
Packit 597cd4
 * Returns 0 on success
Packit 597cd4
 */
Packit 597cd4
static int ieee8023_bld_linkagg_tlv(struct ieee8023_data *bd,
Packit 597cd4
				    struct lldp_agent *agent)
Packit 597cd4
{
Packit 597cd4
	int rc = 0;
Packit 597cd4
	struct unpacked_tlv *tlv = NULL;
Packit 597cd4
	struct tlv_info_8023_linkagg linkagg;
Packit 597cd4
Packit 597cd4
	/* free old one if it exists */
Packit 597cd4
	FREE_UNPKD_TLV(bd, linkagg);
Packit 597cd4
Packit 597cd4
	if (!is_tlv_txenabled(bd->ifname, agent->type,
Packit 597cd4
			      TLVID_8023(LLDP_8023_LINK_AGGREGATION))) {
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	/* load from config */
Packit 597cd4
	memset(&linkagg, 0, sizeof(linkagg));
Packit 597cd4
	if (get_config_tlvinfo_bin(bd->ifname, agent->type,
Packit 597cd4
				   TLVID_8023(LLDP_8023_LINK_AGGREGATION),
Packit 597cd4
				   &linkagg, sizeof(linkagg))) {
Packit 597cd4
		hton24(linkagg.oui, OUI_IEEE_8023);
Packit 597cd4
		linkagg.sub = LLDP_8023_LINK_AGGREGATION;
Packit 597cd4
		if (is_bond(bd->ifname)) {
Packit 597cd4
			linkagg.status = (LLDP_8023_LINKAGG_CAPABLE |
Packit 597cd4
					  LLDP_8023_LINKAGG_ENABLED);
Packit 597cd4
			linkagg.portid =  htonl(get_master(bd->ifname));
Packit 597cd4
		}
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	tlv = create_tlv();
Packit 597cd4
	if (!tlv)
Packit 597cd4
		goto out_err;
Packit 597cd4
Packit 597cd4
	tlv->type = ORG_SPECIFIC_TLV;
Packit 597cd4
	tlv->length = sizeof(linkagg);
Packit 597cd4
	tlv->info = (u8 *)malloc(tlv->length);
Packit 597cd4
	if(!tlv->info) {
Packit 597cd4
		free(tlv);
Packit 597cd4
		tlv = NULL;
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
	memcpy(tlv->info, &linkagg, tlv->length);
Packit 597cd4
	bd->linkagg = tlv;
Packit 597cd4
	rc = 0;
Packit 597cd4
out_err:
Packit 597cd4
	return rc;
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
/*
Packit 597cd4
 * ieee8023_bld_powvmdi_tlv - build the Power via MDI TLV
Packit 597cd4
 * @bd: the med data struct
Packit 597cd4
 *
Packit 597cd4
 * Returns 0 on success
Packit 597cd4
 */
Packit 597cd4
static int ieee8023_bld_powvmdi_tlv(struct ieee8023_data *bd,
Packit 597cd4
				    struct lldp_agent *agent)
Packit 597cd4
{
Packit 597cd4
	int rc = 0;
Packit 597cd4
	struct unpacked_tlv *tlv = NULL;
Packit 597cd4
	struct tlv_info_8023_powvmdi powvmdi;
Packit 597cd4
Packit 597cd4
	/* free old one if it exists */
Packit 597cd4
	FREE_UNPKD_TLV(bd, powvmdi);
Packit 597cd4
Packit 597cd4
	if (!is_tlv_txenabled(bd->ifname, agent->type,
Packit 597cd4
			      TLVID_8023(LLDP_8023_POWER_VIA_MDI))) {
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	/* not recommended for LLDP-MED */
Packit 597cd4
	if (is_tlv_txenabled(bd->ifname, agent->type,
Packit 597cd4
			     TLVID_MED(LLDP_MED_RESERVED))) {
Packit 597cd4
		/* do not fail */
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	/* TODO: currently only supports config */
Packit 597cd4
	memset(&powvmdi, 0, sizeof(powvmdi));
Packit 597cd4
	if (get_config_tlvinfo_bin(bd->ifname, agent->type,
Packit 597cd4
				   TLVID_8023(LLDP_8023_POWER_VIA_MDI),
Packit 597cd4
				   &powvmdi, sizeof(powvmdi))) {
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	tlv = create_tlv();
Packit 597cd4
	if (!tlv)
Packit 597cd4
		goto out_err;
Packit 597cd4
Packit 597cd4
	tlv->type = ORG_SPECIFIC_TLV;
Packit 597cd4
	tlv->length = sizeof(powvmdi);
Packit 597cd4
	tlv->info = (u8 *)malloc(tlv->length);
Packit 597cd4
	if(!tlv->info) {
Packit 597cd4
		free(tlv);
Packit 597cd4
		tlv = NULL;
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
	memcpy(tlv->info, &powvmdi, tlv->length);
Packit 597cd4
	bd->powvmdi = tlv;
Packit 597cd4
	rc = 0;
Packit 597cd4
out_err:
Packit 597cd4
	return rc;
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
static void ieee8023_free_tlv(struct ieee8023_data *bd)
Packit 597cd4
{
Packit 597cd4
	if (bd) {
Packit 597cd4
		FREE_UNPKD_TLV(bd, maccfg);
Packit 597cd4
		FREE_UNPKD_TLV(bd, powvmdi);
Packit 597cd4
		FREE_UNPKD_TLV(bd, linkagg);
Packit 597cd4
		FREE_UNPKD_TLV(bd, maxfs);
Packit 597cd4
	}
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
static int ieee8023_bld_tlv(struct ieee8023_data *bd, struct lldp_agent *agent)
Packit 597cd4
{
Packit 597cd4
	if (!port_find_by_ifindex(get_ifidx(bd->ifname)))
Packit 597cd4
		return -EEXIST;
Packit 597cd4
Packit 597cd4
	if (ieee8023_bld_maccfg_tlv(bd, agent)) {
Packit 597cd4
		LLDPAD_DBG("%s:%s:ieee8023_bld_macfg_tlv() failed\n",
Packit 597cd4
			   __func__, bd->ifname);
Packit 597cd4
		return 0;
Packit 597cd4
	}
Packit 597cd4
	if (ieee8023_bld_powvmdi_tlv(bd, agent)) {
Packit 597cd4
		LLDPAD_DBG("%s:%s:ieee8023_bld_powvmdi_tlv() failed\n",
Packit 597cd4
			   __func__, bd->ifname);
Packit 597cd4
		return 0;
Packit 597cd4
	}
Packit 597cd4
	if (ieee8023_bld_linkagg_tlv(bd, agent)) {
Packit 597cd4
		LLDPAD_DBG("%s:%s:ieee8023_bld_linkagg_tlv() failed\n",
Packit 597cd4
			   __func__, bd->ifname);
Packit 597cd4
		return 0;
Packit 597cd4
	}
Packit 597cd4
	if (ieee8023_bld_maxfs_tlv(bd, agent)) {
Packit 597cd4
		LLDPAD_DBG("%s:%s:ieee8023_bld_maxfs_tlv() failed\n",
Packit 597cd4
			   __func__, bd->ifname);
Packit 597cd4
		return 0;
Packit 597cd4
	}
Packit 597cd4
	return 0;
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
static void ieee8023_free_data(struct ieee8023_user_data *ud)
Packit 597cd4
{
Packit 597cd4
	struct ieee8023_data *bd;
Packit 597cd4
	if (ud) {
Packit 597cd4
		while (!LIST_EMPTY(&ud->head)) {
Packit 597cd4
			bd = LIST_FIRST(&ud->head);
Packit 597cd4
			LIST_REMOVE(bd, entry);
Packit 597cd4
			ieee8023_free_tlv(bd);
Packit 597cd4
			free(bd);
Packit 597cd4
		}
Packit 597cd4
	}
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
struct packed_tlv *ieee8023_gettlv(struct port *port,
Packit 597cd4
				   struct lldp_agent *agent)
Packit 597cd4
{
Packit 597cd4
	int size;
Packit 597cd4
	struct ieee8023_data *bd;
Packit 597cd4
	struct packed_tlv *ptlv = NULL;
Packit 597cd4
Packit 597cd4
	bd = ieee8023_data(port->ifname, agent->type);
Packit 597cd4
	if (!bd)
Packit 597cd4
		goto out_err;
Packit 597cd4
Packit 597cd4
	ieee8023_free_tlv(bd);
Packit 597cd4
	if (ieee8023_bld_tlv(bd, agent)) {
Packit 597cd4
		LLDPAD_DBG("%s:%s ieee8023_bld_tlv failed\n",
Packit 597cd4
			__func__, port->ifname);
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	size = TLVSIZE(bd->maccfg)
Packit 597cd4
		+ TLVSIZE(bd->powvmdi)
Packit 597cd4
		+ TLVSIZE(bd->linkagg)
Packit 597cd4
		+ TLVSIZE(bd->maxfs);
Packit 597cd4
	if (!size)
Packit 597cd4
		goto out_err;
Packit 597cd4
Packit 597cd4
	ptlv = create_ptlv();
Packit 597cd4
	if (!ptlv)
Packit 597cd4
		goto out_err;
Packit 597cd4
Packit 597cd4
	ptlv->tlv = malloc(size);
Packit 597cd4
	if (!ptlv->tlv)
Packit 597cd4
		goto out_free;
Packit 597cd4
Packit 597cd4
	ptlv->size = 0;
Packit 597cd4
	PACK_TLV_AFTER(bd->maccfg, ptlv, size, out_free);
Packit 597cd4
	PACK_TLV_AFTER(bd->powvmdi, ptlv, size, out_free);
Packit 597cd4
	PACK_TLV_AFTER(bd->linkagg, ptlv, size, out_free);
Packit 597cd4
	PACK_TLV_AFTER(bd->maxfs, ptlv, size, out_free);
Packit 597cd4
	return ptlv;
Packit 597cd4
out_free:
Packit 597cd4
	ptlv = free_pkd_tlv(ptlv);
Packit 597cd4
out_err:
Packit 597cd4
	LLDPAD_DBG("%s:%s: failed\n", __func__, port->ifname);
Packit 597cd4
	return NULL;
Packit 597cd4
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
Packit 597cd4
void ieee8023_ifdown(char *ifname, struct lldp_agent *agent)
Packit 597cd4
{
Packit 597cd4
	struct ieee8023_data *bd;
Packit 597cd4
Packit 597cd4
	bd = ieee8023_data(ifname, agent->type);
Packit 597cd4
	if (!bd)
Packit 597cd4
		goto out_err;
Packit 597cd4
Packit 597cd4
	LIST_REMOVE(bd, entry);
Packit 597cd4
	ieee8023_free_tlv(bd);
Packit 597cd4
	free(bd);
Packit 597cd4
	LLDPAD_INFO("%s:port %s removed\n", __func__, ifname);
Packit 597cd4
	return;
Packit 597cd4
out_err:
Packit 597cd4
	LLDPAD_INFO("%s:port %s adding failed\n", __func__, ifname);
Packit 597cd4
Packit 597cd4
	return;
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
void ieee8023_ifup(char *ifname, struct lldp_agent *agent)
Packit 597cd4
{
Packit 597cd4
	struct ieee8023_data *bd;
Packit 597cd4
	struct ieee8023_user_data *ud;
Packit 597cd4
Packit 597cd4
	bd = ieee8023_data(ifname, agent->type);
Packit 597cd4
	if (bd) {
Packit 597cd4
		LLDPAD_INFO("%s:%s exists\n", __func__, ifname);
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	/* not found, alloc/init per-port tlv data */
Packit 597cd4
	bd = (struct ieee8023_data *) malloc(sizeof(*bd));
Packit 597cd4
	if (!bd) {
Packit 597cd4
		LLDPAD_INFO("%s:%s malloc %zu failed\n",
Packit 597cd4
			 __func__, ifname, sizeof(*bd));
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
	memset(bd, 0, sizeof(struct ieee8023_data));
Packit 597cd4
	strncpy(bd->ifname, ifname, IFNAMSIZ);
Packit 597cd4
	bd->agenttype = agent->type;
Packit 597cd4
Packit 597cd4
	if (ieee8023_bld_tlv(bd, agent)) {
Packit 597cd4
		LLDPAD_INFO("%s:%s mand_bld_tlv failed\n", __func__, ifname);
Packit 597cd4
		free(bd);
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
Packit 597cd4
	ud = find_module_user_data_by_id(&lldp_head, LLDP_MOD_8023);
Packit 597cd4
	LIST_INSERT_HEAD(&ud->head, bd, entry);
Packit 597cd4
	LLDPAD_INFO("%s:port %s added\n", __func__, ifname);
Packit 597cd4
	return;
Packit 597cd4
out_err:
Packit 597cd4
	LLDPAD_INFO("%s:port %s adding failed\n", __func__, ifname);
Packit 597cd4
	return;
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
struct lldp_module *ieee8023_register(void)
Packit 597cd4
{
Packit 597cd4
	struct lldp_module *mod;
Packit 597cd4
	struct ieee8023_user_data *ud;
Packit 597cd4
Packit 597cd4
	mod = malloc(sizeof(*mod));
Packit 597cd4
	if (!mod) {
Packit 597cd4
		LLDPAD_ERR("failed to malloc LLDP 802.3 module data");
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
	ud = malloc(sizeof(struct ieee8023_user_data));
Packit 597cd4
	if (!ud) {
Packit 597cd4
		free(mod);
Packit 597cd4
		LLDPAD_ERR("failed to malloc LLDP 802.3 module user data");
Packit 597cd4
		goto out_err;
Packit 597cd4
	}
Packit 597cd4
	LIST_INIT(&ud->head);
Packit 597cd4
 	mod->id = LLDP_MOD_8023;
Packit 597cd4
	mod->ops = &ieee8023_ops;
Packit 597cd4
	mod->data = ud;
Packit 597cd4
	LLDPAD_INFO("%s:done\n", __func__);
Packit 597cd4
	return mod;
Packit 597cd4
out_err:
Packit 597cd4
	LLDPAD_INFO("%s:failed\n", __func__);
Packit 597cd4
	return NULL;
Packit 597cd4
Packit 597cd4
}
Packit 597cd4
Packit 597cd4
void ieee8023_unregister(struct lldp_module *mod)
Packit 597cd4
{
Packit 597cd4
	if (mod->data) {
Packit 597cd4
		ieee8023_free_data((struct ieee8023_user_data *) mod->data);
Packit 597cd4
		free(mod->data);
Packit 597cd4
	}
Packit 597cd4
	free(mod);
Packit 597cd4
	LLDPAD_INFO("%s:done\n", __func__);
Packit 597cd4
}