Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ДИПЛОМ_ИПОВС / ВКР ИПОВС / ПИН-42_2019_Золотарев_ИА_Текст_Программы.docx
Скачиваний:
77
Добавлен:
29.10.2021
Размер:
47.77 Кб
Скачать

ПРИЛОЖЕНИЕ 3

Программный модуль автоматизированного управления сервисом протокола быстрой сходимости текст программы

ПМ АУС

Содержание

1. Основной файл кода ПМ АУС 3

2. Файл кода для консольного интерфейса ПМ АУС 14

Основополагающие фрагменты кода ПМ АУС:

  1. Основной файл кода пм аус

#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);

}