|
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 |
}
|