
ПРИЛОЖЕНИЕ 3
Программный модуль автоматизированного управления сервисом протокола быстрой сходимости текст программы
ПМ АУС
Содержание
1. Основной файл кода ПМ АУС 3
2. Файл кода для консольного интерфейса ПМ АУС 14
Основополагающие фрагменты кода ПМ АУС:
Основной файл кода пм аус
#define _GNU_SOURCE
#include <unistd.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <assert.h>
#include <netinet/ether.h>
#include <net/ethernet.h>
#include <fcntl.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/link.h>
#include <event2/event.h>
#include <libubox/list.h>
#include </avl-cmp.h>
#include <libubox/avl.h>
#include <jansson.h>
#include <mstpd/ctl_functions.h>
#include <mstpd/mstp_ctl.h>
#include "linux-switch.h"
#define LSW_LOG_NAME "stp"
#include "log.h"
#define PORT_XPATH "/ietf-interfaces:interfaces/interface/" \
"ieee802-dot1q-bridge:bridge-port/angtel-stp:spanning-tree"
#define BRIDGE_XPATH "/ieee802-dot1q-bridge:bridges/bridge/component"
#define BRIDGE_STP_XPATH BRIDGE_XPATH"/angtel-stp:spanning-tree"
#ifndef GET_NUM_FROM_PRIO
#define GET_NUM_FROM_PRIO(p) (__be16_to_cpu(p) & 0x0FFF)
#endif
#define GET_BRIDGE_PRIO(p) (__be16_to_cpu(p) & 0xF000)
#ifndef SYSFS_PATH_MAX
#define SYSFS_PATH_MAX 256
#endif //SYSFS_PATH_MAX
#ifndef SYSFS_CLASS_NET
#define SYSFS_CLASS_NET "/sys/class/net"
#endif //SYSFS_CLASS_NET
#define STP_STATUS_POLL_PERIOD 3 /* 3 seconds */
enum rcv_data_type {
CTL_MESSAGE,
BRIDGE_DATA,
PORT_DATA
};
struct rcv_data {
enum rcv_data_type type;
union {
struct stp_port *port;
struct stp_bridge *br;
};
bool wait;
};
enum return_codes {
RC_OK = 0,
RC_FATAL = -1,
RC_SOCK_ERR = -2,
};
struct stp_port {
char *name;
struct avl_node entry;
bool deleted;
struct {
CIST_PortStatus portstat;
bool obsolete;
bool status_changed;
bool status_in_db;
bool counters_changed;
bool counters_in_db;
} status;
struct {
bool enable;
bool enable_changed;
struct stp_bridge *br;
bool admin_edge_port;
bool auto_edge_port;
CIST_PortConfig cist;
bool cist_changed;
MSTI_PortConfig msti;
bool msti_changed;
} conf;
};
struct stp_bridge {
char *name;
struct avl_node entry;
bool applied;
bool deleted;
struct {
CIST_BridgeStatus bridgestat;
bool obsolete;
bool changed;
bool in_database;
} status;
struct {
bool enable;
bool enable_changed;
uint8_t bridge_priority;
bool bridge_priority_changed;
CIST_BridgeConfig bridgeconf;
bool bridgeconf_changed;
} conf;
};
struct stp_priv {
struct lsw_module *mod;
evutil_socket_t fd;
struct event *connect_event;
struct event *read_event;
struct event *set_config_event;
struct event *status_poll_timer;
struct avl_tree bridges;
struct avl_tree ports;
bool mstpd_is_on;
bool set_config;
bool get_status;
bool status_changed;
bool pending_deletions;
struct rcv_data rcv_data;
struct nl_cache *nl_cache;
struct {
int cmd;
int lin;
int lout;
} send_recv_params;
};
static int connect_to_daemon(struct stp_priv *stp);
static char *mac_to_str(const uint8_t mac[6])
{
struct ether_addr e = {0};
memcpy(e.ether_addr_octet, mac, 6*sizeof(uint8_t));
return strdup(ether_ntoa(&e));
}
static inline int get_index(struct nl_cache *nl_cache, const char *ifname)
{
return rtnl_link_name2i(nl_cache, ifname);
}
static int send_ctl_message(struct stp_priv *stp, void *inbuf)
{
int cmd = stp->send_recv_params.cmd;
int lin = stp->send_recv_params.lin;
int lout = stp->send_recv_params.lout;
struct ctl_msg_hdr mhdr;
struct msghdr msg;
struct iovec iov[3];
int l;
LogString logs = { .buf = "" };
LogString *log = &logs;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 3;
msg.msg_control = NULL;
msg.msg_controllen = 0;
mhdr.cmd = cmd;
mhdr.lin = lin;
mhdr.lout = lout;
mhdr.llog = sizeof(log->buf) - 1;
iov[0].iov_base = &mhdr;
iov[0].iov_len = sizeof(mhdr);
iov[1].iov_base = (void *)inbuf;
iov[1].iov_len = lin;
iov[2].iov_base = log->buf;
iov[2].iov_len = 0;
l = sendmsg(stp->fd, &msg, 0);
if (0 > l) {
DLOG_ERR("Error sending message to server: %m");
return RC_SOCK_ERR;
}
if (l != sizeof(mhdr) + lin) {
DLOG_ERR("Error sending message to server: Partial write");
return RC_SOCK_ERR;
}
return RC_OK;
}
static int recv_ctl_message(struct stp_priv *stp, void *outbuf)
{
int cmd = stp->send_recv_params.cmd;
int lin = stp->send_recv_params.lin;
int lout = stp->send_recv_params.lout;
struct ctl_msg_hdr mhdr;
struct msghdr msg;
struct iovec iov[3];
int l;
LogString logs = { .buf = "" };
LogString *log = &logs;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 3;
msg.msg_control = NULL;
msg.msg_controllen = 0;
mhdr.cmd = cmd;
mhdr.lin = lin;
mhdr.lout = lout;
mhdr.llog = sizeof(log->buf) - 1;
iov[0].iov_base = &mhdr;
iov[0].iov_len = sizeof(mhdr);
iov[1].iov_base = outbuf;
iov[1].iov_len = lout;
iov[2].iov_base = log->buf;
iov[2].iov_len = sizeof(log->buf);
l = recvmsg(stp->fd, &msg, 0);
if (0 >= l) {
DLOG_ERR("Error getting message from server: %m");
return RC_SOCK_ERR;
}
if ((sizeof(mhdr) > l)
|| (l != sizeof(mhdr) + mhdr.lout + mhdr.llog)
|| (mhdr.cmd != cmd)
) {
DLOG_ERR("Error getting message from server: Bad format");
return RC_FATAL;
}
if (mhdr.lout != lout) {
DLOG_ERR("Error, unexpected result length %d, expected %d\n",
mhdr.lout, lout);
return RC_FATAL;
}
if (sizeof(log->buf) <= mhdr.llog) {
DLOG_ERR("Invalid log message length %d", mhdr.llog);
return RC_FATAL;
}
if (mhdr.res) {
if (mhdr.llog != 0) {
log->buf[mhdr.llog] = 0;
DLOG_FUNC(STDLOG_ERR, "%s", log->buf);
} else {
DLOG(STDLOG_ERR, "Error receiving ctl message response");
}
return RC_FATAL;
}
return RC_OK;
}
static int not_dot_dotdot(const struct dirent *entry)
{
const char *n = entry->d_name;
return !('.' == n[0] && (0 == n[1] || ('.' == n[1] && 0 == n[2])));
}
static int get_port_list(const char *br_ifname, struct dirent ***namelist)
{
int res;
char buf[SYSFS_PATH_MAX];
snprintf(buf, sizeof(buf), SYSFS_CLASS_NET "/%.230s/brif", br_ifname);
if (0 > (res = scandir(buf, namelist, not_dot_dotdot, versionsort)))
DLOG_FUNC(STDLOG_ERR, "Error getting list of all ports of bridge %s", br_ifname);
return res;
}
static int _CTL_set_cist_bridge_config(struct stp_priv *stp, int br_index, CIST_BridgeConfig *cfg)
{
struct set_cist_bridge_config_IN in0, *in = &in0;
in->br_index = br_index;
in->cfg = *cfg;
stp->send_recv_params.cmd = CMD_CODE_set_cist_bridge_config;
stp->send_recv_params.lin = sizeof(*in);
stp->send_recv_params.lout = 0;
return send_ctl_message(stp, in);
}
static int _CTL_set_msti_bridge_config(struct stp_priv *stp,
int br_index,
__u16 mstid,
__u8 bridge_priority)
{
struct set_msti_bridge_config_IN in0, *in = &in0;
in->br_index = br_index;
in->mstid = mstid;
in->bridge_priority = bridge_priority;
stp->send_recv_params.cmd = CMD_CODE_set_msti_bridge_config;
stp->send_recv_params.lin = sizeof(*in);
stp->send_recv_params.lout = 0;
return send_ctl_message(stp, in);
}
static int _CTL_set_cist_port_config(struct stp_priv *stp,
int br_index,
int port_index,
CIST_PortConfig *cfg)
{
struct set_cist_port_config_IN in0, *in = &in0;
in->br_index = br_index;
in->port_index = port_index;
in->cfg = *cfg;
stp->send_recv_params.cmd = CMD_CODE_set_cist_port_config;
stp->send_recv_params.lin = sizeof(*in);
stp->send_recv_params.lout = 0;
return send_ctl_message(stp, in);
}
static int _CTL_set_msti_port_config(struct stp_priv *stp,
int br_index,
int port_index,
__u16 mstid,
MSTI_PortConfig *cfg)
{
struct set_msti_port_config_IN in0, *in = &in0;
in->br_index = br_index;
in->port_index = port_index;
in->mstid = mstid;
in->cfg = *cfg;
stp->send_recv_params.cmd = CMD_CODE_set_msti_port_config;
stp->send_recv_params.lin = sizeof(*in);
stp->send_recv_params.lout = 0;
return send_ctl_message(stp, in);
}
static int _CTL_get_cist_bridge_status(struct stp_priv *stp, int br_index)
{
struct get_cist_bridge_status_IN in0, *in = &in0;
in->br_index = br_index;
stp->send_recv_params.cmd = CMD_CODE_get_cist_bridge_status;
stp->send_recv_params.lin = sizeof(*in);
stp->send_recv_params.lout = sizeof(struct get_cist_bridge_status_OUT);
return send_ctl_message(stp, in);
}
static int _CTL_get_cist_port_status(struct stp_priv *stp, int br_index, int port_index)
{
struct get_cist_port_status_IN in0, *in = &in0;
in->br_index = br_index;
in->port_index = port_index;
stp->send_recv_params.cmd = CMD_CODE_get_cist_port_status;
stp->send_recv_params.lin = sizeof(*in);
stp->send_recv_params.lout = sizeof(struct get_cist_port_status_OUT);
return send_ctl_message(stp, in);
}