From 97d51af699dde0d91ee7bd41203a24a20a839de1 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 31 Jan 2019 23:02:51 -0800 Subject: [PATCH 01/23] MCLAG feature for sonic --- dockers/docker-iccpd/Dockerfile | 30 + dockers/docker-iccpd/Dockerfile.j2 | 35 + .../docker-iccpd/base_image_files/mclagdctl | 10 + dockers/docker-iccpd/iccpd.j2 | 8 + dockers/docker-iccpd/iccpd.sh | 17 + dockers/docker-iccpd/start.sh | 18 + dockers/docker-iccpd/supervisord.conf | 29 + files/build_templates/docker_image_ctl.j2 | 3 + files/build_templates/iccpd.service.j2 | 13 + rules/docker-iccpd.mk | 14 + rules/iccpd.mk | 13 + src/iccpd/Makefile | 33 + src/iccpd/debian/DEBIAN/control | 12 + src/iccpd/include/app_csm.h | 71 + src/iccpd/include/cmd_option.h | 82 + src/iccpd/include/iccp_cli.h | 55 + src/iccpd/include/iccp_cmd.h | 27 + src/iccpd/include/iccp_cmd_show.h | 35 + src/iccpd/include/iccp_consistency_check.h | 42 + src/iccpd/include/iccp_csm.h | 162 ++ src/iccpd/include/iccp_ifm.h | 42 + src/iccpd/include/iccp_netlink.h | 44 + src/iccpd/include/logger.h | 67 + src/iccpd/include/mlacp_fsm.h | 102 + src/iccpd/include/mlacp_link_handler.h | 51 + src/iccpd/include/mlacp_sync_prepare.h | 54 + src/iccpd/include/mlacp_sync_update.h | 45 + src/iccpd/include/mlacp_tlv.h | 413 ++++ src/iccpd/include/msg_format.h | 427 ++++ src/iccpd/include/port.h | 149 ++ src/iccpd/include/scheduler.h | 58 + src/iccpd/include/system.h | 83 + src/iccpd/src/Makefile | 55 + src/iccpd/src/app_csm.c | 312 +++ src/iccpd/src/cmd_option.c | 262 +++ src/iccpd/src/iccp_cli.c | 363 ++++ src/iccpd/src/iccp_cmd.c | 160 ++ src/iccpd/src/iccp_cmd_show.c | 474 +++++ src/iccpd/src/iccp_consistency_check.c | 175 ++ src/iccpd/src/iccp_csm.c | 746 +++++++ src/iccpd/src/iccp_ifm.c | 1037 ++++++++++ src/iccpd/src/iccp_main.c | 186 ++ src/iccpd/src/iccp_netlink.c | 1136 +++++++++++ src/iccpd/src/logger.c | 124 ++ src/iccpd/src/mclagdctl/Makefile | 28 + src/iccpd/src/mclagdctl/mclagdctl | Bin 0 -> 46856 bytes src/iccpd/src/mclagdctl/mclagdctl.c | 792 ++++++++ src/iccpd/src/mclagdctl/mclagdctl.h | 177 ++ src/iccpd/src/mclagdctl/mclagdctl.o | Bin 0 -> 86776 bytes src/iccpd/src/mlacp_fsm.c | 1136 +++++++++++ src/iccpd/src/mlacp_link_handler.c | 1789 +++++++++++++++++ src/iccpd/src/mlacp_sync_prepare.c | 789 ++++++++ src/iccpd/src/mlacp_sync_update.c | 741 +++++++ src/iccpd/src/port.c | 711 +++++++ src/iccpd/src/scheduler.c | 639 ++++++ src/iccpd/src/system.c | 185 ++ 56 files changed, 14261 insertions(+) create mode 100644 dockers/docker-iccpd/Dockerfile create mode 100644 dockers/docker-iccpd/Dockerfile.j2 create mode 100644 dockers/docker-iccpd/base_image_files/mclagdctl create mode 100644 dockers/docker-iccpd/iccpd.j2 create mode 100644 dockers/docker-iccpd/iccpd.sh create mode 100644 dockers/docker-iccpd/start.sh create mode 100644 dockers/docker-iccpd/supervisord.conf create mode 100644 files/build_templates/iccpd.service.j2 create mode 100644 rules/docker-iccpd.mk create mode 100644 rules/iccpd.mk create mode 100644 src/iccpd/Makefile create mode 100644 src/iccpd/debian/DEBIAN/control create mode 100644 src/iccpd/include/app_csm.h create mode 100644 src/iccpd/include/cmd_option.h create mode 100644 src/iccpd/include/iccp_cli.h create mode 100644 src/iccpd/include/iccp_cmd.h create mode 100644 src/iccpd/include/iccp_cmd_show.h create mode 100644 src/iccpd/include/iccp_consistency_check.h create mode 100644 src/iccpd/include/iccp_csm.h create mode 100644 src/iccpd/include/iccp_ifm.h create mode 100644 src/iccpd/include/iccp_netlink.h create mode 100644 src/iccpd/include/logger.h create mode 100644 src/iccpd/include/mlacp_fsm.h create mode 100644 src/iccpd/include/mlacp_link_handler.h create mode 100644 src/iccpd/include/mlacp_sync_prepare.h create mode 100644 src/iccpd/include/mlacp_sync_update.h create mode 100644 src/iccpd/include/mlacp_tlv.h create mode 100644 src/iccpd/include/msg_format.h create mode 100644 src/iccpd/include/port.h create mode 100644 src/iccpd/include/scheduler.h create mode 100644 src/iccpd/include/system.h create mode 100644 src/iccpd/src/Makefile create mode 100644 src/iccpd/src/app_csm.c create mode 100644 src/iccpd/src/cmd_option.c create mode 100644 src/iccpd/src/iccp_cli.c create mode 100644 src/iccpd/src/iccp_cmd.c create mode 100644 src/iccpd/src/iccp_cmd_show.c create mode 100644 src/iccpd/src/iccp_consistency_check.c create mode 100644 src/iccpd/src/iccp_csm.c create mode 100644 src/iccpd/src/iccp_ifm.c create mode 100644 src/iccpd/src/iccp_main.c create mode 100644 src/iccpd/src/iccp_netlink.c create mode 100644 src/iccpd/src/logger.c create mode 100644 src/iccpd/src/mclagdctl/Makefile create mode 100755 src/iccpd/src/mclagdctl/mclagdctl create mode 100644 src/iccpd/src/mclagdctl/mclagdctl.c create mode 100644 src/iccpd/src/mclagdctl/mclagdctl.h create mode 100644 src/iccpd/src/mclagdctl/mclagdctl.o create mode 100644 src/iccpd/src/mlacp_fsm.c create mode 100644 src/iccpd/src/mlacp_link_handler.c create mode 100644 src/iccpd/src/mlacp_sync_prepare.c create mode 100644 src/iccpd/src/mlacp_sync_update.c create mode 100644 src/iccpd/src/port.c create mode 100644 src/iccpd/src/scheduler.c create mode 100644 src/iccpd/src/system.c diff --git a/dockers/docker-iccpd/Dockerfile b/dockers/docker-iccpd/Dockerfile new file mode 100644 index 000000000000..d932ff955561 --- /dev/null +++ b/dockers/docker-iccpd/Dockerfile @@ -0,0 +1,30 @@ +FROM docker-config-engine + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +RUN apt-get install -f -y libdbus-1-3 libdaemon0 libjansson4 + +## Install redis-tools dependencies +## TODO: implicitly install dependencies +RUN apt-get -y install libjemalloc1 +RUN apt-get -y install libpython2.7 +RUN apt-get -y install ebtables +RUN apt-get install -f kmod + +COPY \ +debs/libnl-3-200_3.2.27-2_amd64.deb debs/libnl-route-3-200_3.2.27-2_amd64.deb debs/libnl-genl-3-200_3.2.27-2_amd64.deb debs/libnl-nf-3-200_3.2.27-2_amd64.deb debs/libhiredis0.13_0.13.3-2_amd64.deb debs/libnl-cli-3-200_3.2.27-2_amd64.deb debs/libswsscommon_1.0.0_amd64.deb debs/libsairedis_1.0.0_amd64.deb debs/libsaimetadata_1.0.0_amd64.deb debs/libteam5_1.26-1_amd64.deb debs/python-swsscommon_1.0.0_amd64.deb debs/swss_1.0.0_amd64.deb debs/redis-tools_3.2.4-1~bpo8+1_amd64.deb debs/iccpd_0.0.5_amd64.deb debs/ + +RUN dpkg -i \ +debs/libnl-3-200_3.2.27-2_amd64.deb debs/libnl-route-3-200_3.2.27-2_amd64.deb debs/libnl-genl-3-200_3.2.27-2_amd64.deb debs/libnl-nf-3-200_3.2.27-2_amd64.deb debs/libhiredis0.13_0.13.3-2_amd64.deb debs/libnl-cli-3-200_3.2.27-2_amd64.deb debs/libswsscommon_1.0.0_amd64.deb debs/libsairedis_1.0.0_amd64.deb debs/libsaimetadata_1.0.0_amd64.deb debs/libteam5_1.26-1_amd64.deb debs/python-swsscommon_1.0.0_amd64.deb debs/swss_1.0.0_amd64.deb debs/redis-tools_3.2.4-1~bpo8+1_amd64.deb debs/iccpd_0.0.5_amd64.deb + +COPY ["start.sh", "iccpd.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["iccpd.j2", "/usr/share/sonic/templates/"] + +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] \ No newline at end of file diff --git a/dockers/docker-iccpd/Dockerfile.j2 b/dockers/docker-iccpd/Dockerfile.j2 new file mode 100644 index 000000000000..7f09c6b8ccd3 --- /dev/null +++ b/dockers/docker-iccpd/Dockerfile.j2 @@ -0,0 +1,35 @@ +FROM docker-config-engine + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +RUN apt-get install -f -y libdbus-1-3 libdaemon0 libjansson4 + +## Install redis-tools dependencies +## TODO: implicitly install dependencies +RUN apt-get -y install libjemalloc1 +RUN apt-get -y install libpython2.7 +RUN apt-get -y install ebtables +RUN apt-get install -f kmod + +COPY \ +{% for deb in docker_iccpd_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_iccpd_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "iccpd.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["iccpd.j2", "/usr/share/sonic/templates/"] + +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-iccpd/base_image_files/mclagdctl b/dockers/docker-iccpd/base_image_files/mclagdctl new file mode 100644 index 000000000000..7c0b45dd0625 --- /dev/null +++ b/dockers/docker-iccpd/base_image_files/mclagdctl @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS iccpd mclagdctl "$@" diff --git a/dockers/docker-iccpd/iccpd.j2 b/dockers/docker-iccpd/iccpd.j2 new file mode 100644 index 000000000000..c4e6e26b10c0 --- /dev/null +++ b/dockers/docker-iccpd/iccpd.j2 @@ -0,0 +1,8 @@ +{% for mclag_id in MC_LAG %} +mclag_id:{{mclag_id}} + local_ip:{{MC_LAG[mclag_id]['local_ip']}} + peer_ip:{{MC_LAG[mclag_id]['peer_ip']}} + peer_link:{{MC_LAG[mclag_id]['peer_link']}} + bind_lacp:{{MC_LAG[mclag_id]['bind_lacp']}} +{% endfor %} + diff --git a/dockers/docker-iccpd/iccpd.sh b/dockers/docker-iccpd/iccpd.sh new file mode 100644 index 000000000000..d3b2888344ac --- /dev/null +++ b/dockers/docker-iccpd/iccpd.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +function start_app { + rm -f /var/run/iccpd/* + mclagsyncd & + iccpd +} + +function clean_up { + pkill -9 mclagsyncd + pkill -9 iccpd + exit +} + +trap clean_up SIGTERM SIGKILL +start_app +read diff --git a/dockers/docker-iccpd/start.sh b/dockers/docker-iccpd/start.sh new file mode 100644 index 000000000000..d17634cb836a --- /dev/null +++ b/dockers/docker-iccpd/start.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + + +ICCPD_CONF_PATH=/etc/iccpd + +rm -rf $ICCPD_CONF_PATH +mkdir -p $ICCPD_CONF_PATH + +sonic-cfggen -d -t /usr/share/sonic/templates/iccpd.j2 > $ICCPD_CONF_PATH/iccpd.conf + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start iccpd diff --git a/dockers/docker-iccpd/supervisord.conf b/dockers/docker-iccpd/supervisord.conf new file mode 100644 index 000000000000..dc71f07c6c30 --- /dev/null +++ b/dockers/docker-iccpd/supervisord.conf @@ -0,0 +1,29 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:iccpd] +command=/usr/bin/iccpd.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 index a3cbf5adbae7..df24f9c95bc3 100644 --- a/files/build_templates/docker_image_ctl.j2 +++ b/files/build_templates/docker_image_ctl.j2 @@ -137,6 +137,9 @@ start() { -v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \ {%- if docker_container_name != "database" %} -v /usr/share/sonic/device/$PLATFORM/$HWSKU:/usr/share/sonic/hwsku:ro \ +{%- endif %} +{%- if docker_container_name == "iccpd" %} + -v /lib/modules:/lib/modules:ro \ {%- endif %} --tmpfs /tmp \ --tmpfs /var/tmp \ diff --git a/files/build_templates/iccpd.service.j2 b/files/build_templates/iccpd.service.j2 new file mode 100644 index 000000000000..17017ef1549e --- /dev/null +++ b/files/build_templates/iccpd.service.j2 @@ -0,0 +1,13 @@ +[Unit] +Description=ICCPD container +Requires=updategraph.service swss.service teamd.service +After=updategraph.service swss.service teamd.service + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start +ExecStart=/usr/bin/{{docker_container_name}}.sh attach +ExecStop=/usr/bin/{{docker_container_name}}.sh stop + +[Install] +WantedBy=multi-user.target diff --git a/rules/docker-iccpd.mk b/rules/docker-iccpd.mk new file mode 100644 index 000000000000..c15e95694ba0 --- /dev/null +++ b/rules/docker-iccpd.mk @@ -0,0 +1,14 @@ +# docker image for iccpd agent + +DOCKER_ICCPD = docker-iccpd.gz +$(DOCKER_ICCPD)_PATH = $(DOCKERS_PATH)/docker-iccpd +$(DOCKER_ICCPD)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(ICCPD) +$(DOCKER_ICCPD)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ICCPD) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ICCPD) + +$(DOCKER_ICCPD)_CONTAINER_NAME = iccpd +$(DOCKER_ICCPD)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ICCPD)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_ICCPD)_BASE_IMAGE_FILES += mclagdctl:/usr/bin/mclagdctl diff --git a/rules/iccpd.mk b/rules/iccpd.mk new file mode 100644 index 000000000000..1923a9a2a62d --- /dev/null +++ b/rules/iccpd.mk @@ -0,0 +1,13 @@ +# iccpd package + +ICCPD_VERSION = 0.0.5 + +ICCPD = iccpd_$(ICCPD_VERSION)_amd64.deb +$(ICCPD)_DEPENDS += $(LIBNL_GENL3_DEV) $(LIBNL_CLI_DEV) +$(ICCPD)_RDEPENDS += $(LIBNL_GENL3) $(LIBNL_CLI) +$(ICCPD)_SRC_PATH = $(SRC_PATH)/iccpd +SONIC_MAKE_DEBS += $(ICCPD) + +# Export these variables so they can be used in a sub-make +export ICCPD_VERSION +export ICCPD diff --git a/src/iccpd/Makefile b/src/iccpd/Makefile new file mode 100644 index 000000000000..5dbbd8b89bd0 --- /dev/null +++ b/src/iccpd/Makefile @@ -0,0 +1,33 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = iccpd_$(ICCPD_VERSION)_amd64.deb +DEB_PATH = debian + +all: iccpd-build mclagdctl-build + +iccpd-build: + make -C src + +mclagdctl-build: + make -C src/mclagdctl + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + make all + if [ ! -d $(DEB_PATH)/usr/bin ]; then + mkdir -p $(DEB_PATH)/usr/bin + fi + cp iccpd $(DEB_PATH)/usr/bin/iccpd + cp src/mclagdctl/mclagdctl $(DEB_PATH)/usr/bin/mclagdctl + md5sum $(DEB_PATH)/usr/bin/iccpd > $(DEB_PATH)/DEBIAN/md5sums + md5sum $(DEB_PATH)/usr/bin/mclagdctl >> $(DEB_PATH)/DEBIAN/md5sums + dpkg-deb -b $(DEB_PATH) $(DEST)/$(MAIN_TARGET) + +clean: iccpd-clean mclagdctl-clean + +iccpd-clean: + make -C src clean + +mclagdctl-clean: + make -C src/mclagdctl clean diff --git a/src/iccpd/debian/DEBIAN/control b/src/iccpd/debian/DEBIAN/control new file mode 100644 index 000000000000..cedfa03f37c0 --- /dev/null +++ b/src/iccpd/debian/DEBIAN/control @@ -0,0 +1,12 @@ +Package: iccpd-0.0.5-amd64 +Source: nps +Version: 0.0.5 +Architecture: amd64 +Maintainer: Simon Ji +Installed-Size: 1508 +Depends: +Section: main +Priority: extra +Homepage: https://github.com/NephosInc/SONiC +Description: + diff --git a/src/iccpd/include/app_csm.h b/src/iccpd/include/app_csm.h new file mode 100644 index 000000000000..6a5e554bc73e --- /dev/null +++ b/src/iccpd/include/app_csm.h @@ -0,0 +1,71 @@ +/* +* app_csm.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef APP_CSM_H_ +#define APP_CSM_H_ + +#include + +#include "../include/mlacp_fsm.h" + +struct CSM; + +enum APP_CONNECTION_STATE { + APP_NONEXISTENT, + APP_RESET, + APP_CONNSENT, + APP_CONNREC, + APP_CONNECTING, + APP_OPERATIONAL +}; + +typedef enum APP_CONNECTION_STATE APP_CONNECTION_STATE_E; + +struct AppCSM { + struct mLACP mlacp; + APP_CONNECTION_STATE_E current_state; + + uint32_t rx_connect_msg_id; + uint32_t tx_connect_msg_id; + uint32_t invalid_msg_id; + + TAILQ_HEAD(app_msg_list, Msg) app_msg_list; + + uint8_t invalid_msg :1; + uint8_t nak_msg :1; +}; + +void app_csm_init(struct CSM*, int all); +void app_csm_finalize(struct CSM*); +void app_csm_transit(struct CSM*); +int app_csm_prepare_iccp_msg(struct CSM*, char*, size_t); +void app_csm_enqueue_msg(struct CSM*, struct Msg*); +struct Msg* app_csm_dequeue_msg(struct CSM*); +void app_csm_correspond_from_msg(struct CSM*, struct Msg*); +void app_csm_correspond_from_connect_msg(struct CSM*, struct Msg*); +void app_csm_correspond_from_connect_ack_msg(struct CSM*, struct Msg*); +int app_csm_prepare_nak_msg(struct CSM*, char*, size_t); +int app_csm_prepare_connect_msg(struct CSM*, char*, size_t); +int app_csm_prepare_connect_ack_msg(struct CSM*, char*, size_t); + +#endif /* APP_CSM_H_ */ diff --git a/src/iccpd/include/cmd_option.h b/src/iccpd/include/cmd_option.h new file mode 100644 index 000000000000..d81249ea5e93 --- /dev/null +++ b/src/iccpd/include/cmd_option.h @@ -0,0 +1,82 @@ +/* +* cmd_option.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef CMD_OPTION_H_ +#define CMD_OPTION_H_ + +#include +#include +#include +#include +#include +#include + +#define OPTION_MAX_LEN 256 +#define MSG_LEN 81 + +#define CMD_OPTION_PARSER_INIT_VALUE \ +{ \ + .log_file_path = "/var/log/iccpd.log", \ + .pid_file_path = "/var/run/iccpd/iccpd.pid", \ + .cmd_file_path = "/var/run/iccpd/iccpd.vty", \ + .config_file_path = "/etc/iccpd/iccpd.conf", \ + .mclagdctl_file_path = "/var/run/iccpd/mclagdctl.sock", \ + .console_log = 0, \ + .telnet_port = 2015, \ + .init = cmd_option_parser_init, \ + .finalize = cmd_option_parser_finalize, \ + .dump_usage = cmd_option_parser_dump_usage, \ + .parse = cmd_option_parser_parse, \ +} + +struct CmdOption { + char* desc; + char* option; + char* parameter; + LIST_ENTRY(CmdOption) next; +}; + +struct CmdOptionParser { + char* log_file_path; + char* pid_file_path; + char* cmd_file_path; + char* config_file_path; + char *mclagdctl_file_path; + uint8_t console_log; + uint16_t telnet_port; + LIST_HEAD(option_list, CmdOption) option_list; + int (*parse)(struct CmdOptionParser*, int, char*[]); + void (*init)(struct CmdOptionParser*); + void (*finalize)(struct CmdOptionParser*); + void (*dump_usage)(struct CmdOptionParser*, char*); +}; + +int cmd_option_parser_parse(struct CmdOptionParser*, int, char*[]); +struct CmdOption* cmd_option_add(struct CmdOptionParser*, char*); +struct CmdOption* cmd_option_find(struct CmdOptionParser*, char*); +void cmd_option_delete(struct CmdOption*); +void cmd_option_parser_init(struct CmdOptionParser*); +void cmd_option_parser_finalize(struct CmdOptionParser*); +void cmd_option_parser_dump_usage(struct CmdOptionParser*, char*); + +#endif /* CMD_OPTION_H_ */ diff --git a/src/iccpd/include/iccp_cli.h b/src/iccpd/include/iccp_cli.h new file mode 100644 index 000000000000..1c504ed12940 --- /dev/null +++ b/src/iccpd/include/iccp_cli.h @@ -0,0 +1,55 @@ +/* +* iccp_cli.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef _ICCP_CLI_H +#define _ICCP_CLI_H + +#include + +struct CSM; + +typedef enum { + QU_TYPE_NONE, + QU_TYPE_MLAG_ADD_PO +} cli_queue_type_et; + +typedef struct cli_param_queue { + char ifname[16]; + cli_queue_type_et type; + int param; + int itf_add; + LIST_ENTRY(cli_param_queue) cli_queue_next; +} cli_param_queue_st; + +int set_mc_lag_id(struct CSM* csm, uint16_t domain); +int set_peer_link(int mid, const char* ifname); +int set_local_address(int mid, const char* addr); +int set_peer_address(int mid, const char* addr); +int unset_mc_lag_id(struct CSM* csm, uint16_t domain); +int unset_peer_link(int mid); +int unset_local_address(int mid); +int unset_peer_address(int mid); + +int iccp_cli_attach_mclag_domain_to_port_channel(int domain, const char* ifname); +int iccp_cli_detach_mclag_domain_to_port_channel(const char* ifname); +#endif diff --git a/src/iccpd/include/iccp_cmd.h b/src/iccpd/include/iccp_cmd.h new file mode 100644 index 000000000000..a37a90661ea5 --- /dev/null +++ b/src/iccpd/include/iccp_cmd.h @@ -0,0 +1,27 @@ +/* +* iccp_cmd.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef ICCP_CMD_H_ +#define ICCP_CMD_H_ + +#endif /* ICCP_CMD_H_ */ diff --git a/src/iccpd/include/iccp_cmd_show.h b/src/iccpd/include/iccp_cmd_show.h new file mode 100644 index 000000000000..4d3238f95a48 --- /dev/null +++ b/src/iccpd/include/iccp_cmd_show.h @@ -0,0 +1,35 @@ +/* +* iccp_cmd_show.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef _ICCP_CMD_SHOW_H +#define _ICCP_CMD_SHOW_H + +#define ICCP_MAX_PORT_NAME 20 +#define ICCP_MAX_IP_STR_LEN 16 + +extern int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) ; +extern int iccp_arp_dump(char * *buf, int *num, int mclag_id); +extern int iccp_mac_dump(char * *buf, int *num, int mclag_id); +extern int iccp_local_if_dump(char * *buf, int *num,int mclag_id); +extern int iccp_peer_if_dump(char * *buf, int *num, int mclag_id); +#endif diff --git a/src/iccpd/include/iccp_consistency_check.h b/src/iccpd/include/iccp_consistency_check.h new file mode 100644 index 000000000000..e6fe51f364c5 --- /dev/null +++ b/src/iccpd/include/iccp_consistency_check.h @@ -0,0 +1,42 @@ +/* +* iccp_consistency_check.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +* +*/ + +#ifndef _ICCP_CONSISTENCY_CHECK_H +#define _ICCP_CONSISTENCY_CHECK_H + + +enum Reason_ID { + REASON_NONE = 0, + REASON_INTERRFACE_MODE_IS_ASYNC, + REASON_PEER_IF_IP_IS_ASYNC, + REASON_PEER_IF_VLAN_IS_ASYNC, + REASON_MAX_ARRAY_SIZE +}; + +extern const char *reasons[]; + +enum Reason_ID iccp_consistency_check(char* ifname); + + +#endif diff --git a/src/iccpd/include/iccp_csm.h b/src/iccpd/include/iccp_csm.h new file mode 100644 index 000000000000..e57370f3ddd7 --- /dev/null +++ b/src/iccpd/include/iccp_csm.h @@ -0,0 +1,162 @@ +/* +* iccp_csm.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef ICCP_CSM_H_ +#define ICCP_CSM_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "../include/app_csm.h" +#include "../include/msg_format.h" +#include "../include/port.h" + +#define CSM_BUFFER_SIZE 65536 + +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif /*IFNAMSIZ*/ + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif /* INET_ADDRSTRLEN */ + +/* For socket binding */ +#define ICCP_TCP_PORT 8888 +#define MAX_ACCEPT_CONNETIONS 20 + +/* LDP message ID */ +extern uint32_t ICCP_MSG_ID; + +/* Global Buffer */ +extern char g_csm_buf[CSM_BUFFER_SIZE]; + +struct IccpInfo { + uint32_t icc_rg_id; + char sender_name[MAX_L_ICC_SENDER_NAME]; + uint32_t status_code; + uint8_t peer_capability_flag :1; + uint8_t peer_rg_connect_flag :1; + uint8_t sender_capability_flag :1; + uint8_t sender_rg_connect_flag :1; + uint32_t rejected_msg_id; +}; + +/* Receive message node */ +struct Msg { + char* buf; + size_t len; + TAILQ_ENTRY(Msg) tail; +}; + +/* Connection state */ +enum ICCP_CONNECTION_STATE { + ICCP_NONEXISTENT, + ICCP_INITIALIZED, + ICCP_CAPSENT, + ICCP_CAPREC, + ICCP_CONNECTING, + ICCP_OPERATIONAL +}; + +typedef enum ICCP_CONNECTION_STATE ICCP_CONNECTION_STATE_E; + +typedef enum stp_role_type_e { + STP_ROLE_NONE, /* mstp do nothing*/ + STP_ROLE_ACTIVE, /* mstp report port state*/ + STP_ROLE_STANDBY /* mstp fwd bpdu & set port state*/ +} stp_role_type_et; + +/* Connection state machine instance */ +struct CSM { + int mlag_id; + + /* Socket info */ + int sock_fd; + pthread_mutex_t conn_mutex; + time_t connTimePrev; + time_t heartbeat_send_time; + time_t heartbeat_update_time; + char peer_itf_name[IFNAMSIZ]; + char peer_ip[INET_ADDRSTRLEN]; + char sender_ip[INET_ADDRSTRLEN]; + void* sock_read_event_ptr; + + /* Msg queue */ + TAILQ_HEAD(msg_list, Msg) msg_list; + + /* System ID */ + time_t sysid_update_time; + time_t isolate_update_time; + + /* STP role */ + stp_role_type_et role_type; + + /* Peers msg */ + struct LocalInterface* peer_link_if; + struct IccpInfo iccp_info; + struct AppCSM app_csm; + ICCP_CONNECTION_STATE_E current_state; + + /* Statistic info */ + uint64_t icc_msg_in_count; /* ICC message input count */ + uint64_t icc_msg_out_count; /* ICC message Output count */ + uint64_t u_msg_in_count; /* Unknown message Input count */ + uint64_t i_msg_in_count; /* Illegal message Input count */ + + /* Log */ + struct MsgLog msg_log; + + LIST_ENTRY(CSM) next; + LIST_HEAD(csm_if_list, If_info) if_bind_list; +}; +int iccp_csm_send(struct CSM*, char*, int); +int iccp_csm_init_msg(struct Msg**, char*, int); +int iccp_csm_prepare_nak_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_iccp_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_capability_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_rg_connect_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_rg_disconnect_msg(struct CSM*, char*, size_t); +struct Msg* iccp_csm_dequeue_msg(struct CSM*); +void *iccp_get_csm(); +void iccp_csm_init(struct CSM*); +void iccp_csm_transit(struct CSM*); +void iccp_csm_finalize(struct CSM*); +void iccp_csm_status_reset(struct CSM*, int); +void iccp_csm_stp_role_count(struct CSM *csm); +void iccp_csm_msg_list_finalize(struct CSM*); +void iccp_csm_enqueue_msg(struct CSM*, struct Msg*); +void iccp_csm_fill_icc_rg_id_tlv(struct CSM*, ICCHdr*); +void iccp_csm_correspond_from_msg(struct CSM*, struct Msg*); +void iccp_csm_correspond_from_capability_msg(struct CSM*, struct Msg*); +void iccp_csm_correspond_from_rg_connect_msg(struct CSM*, struct Msg*); +void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM*, struct Msg*); + +int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname); + +#endif /* ICCP_CSM_H_ */ diff --git a/src/iccpd/include/iccp_ifm.h b/src/iccpd/include/iccp_ifm.h new file mode 100644 index 000000000000..ec8e2fe00d5e --- /dev/null +++ b/src/iccpd/include/iccp_ifm.h @@ -0,0 +1,42 @@ +/* +* iccp_ifm.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef ICCP_IFM_H +#define ICCP_IFM_H + +#include + +int iccp_sys_local_if_list_get_init(); + +int iccp_arp_get_init(); + +void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]); + +int do_one_neigh_request (struct nlmsghdr *n); + +void iccp_from_netlink_portchannel_state_handler( char * ifname, int state); + +void iccp_get_if_vlan_info_from_netlink(); + +#endif // LACP_IFM_H + diff --git a/src/iccpd/include/iccp_netlink.h b/src/iccpd/include/iccp_netlink.h new file mode 100644 index 000000000000..6f4a2fce3ad0 --- /dev/null +++ b/src/iccpd/include/iccp_netlink.h @@ -0,0 +1,44 @@ +/* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef ICCP_NETLINK_H +#define ICCP_NETLINK_H +#include +#include +#include +#include +#include +#include + +#include + +#include "../include/system.h" +#include "../include/port.h" + +int iccp_get_port_member_list(struct LocalInterface* lif); +void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg); +void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg); +int iccp_system_init_netlink_socket(); +int iccp_init_netlink_event_fd(struct System *sys); +int iccp_handle_events(struct System * sys); +void iccp_netlink_sync_again(); + +#endif + diff --git a/src/iccpd/include/logger.h b/src/iccpd/include/logger.h new file mode 100644 index 000000000000..6a9b64f05112 --- /dev/null +++ b/src/iccpd/include/logger.h @@ -0,0 +1,67 @@ +/* +* logger.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include +#include + +#include "../include/cmd_option.h" + +typedef enum _iccpd_log_level_t +{ + DEBUG_LOG_LEVEL = 0, + INFO_LOG_LEVEL = 1, + NOTICE_LOG_LEVEL = 2, + WARN_LOG_LEVEL = 3, + ERR_LOG_LEVEL = 4, + CRITICAL_LOG_LEVEL = 5 +} _iccpd_log_level_t; + + +#define LOGBUF_SIZE 1024 +#define ICCPD_UTILS_SYSLOG (syslog) + +#define ICCPD_LOG_CRITICAL(tag, format, args...) write_log(CRITICAL_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_ERR(tag, format, args...) write_log(ERR_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_WARN(tag, format, args...) write_log(WARN_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_NOTICE(tag, format, args...) write_log(NOTICE_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_INFO(tag, format, args...) write_log(INFO_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_DEBUG(tag, format, args...) write_log(DEBUG_LOG_LEVEL, tag, format, ##args) + +struct LoggerConfig { + uint8_t console_log_enabled; + uint8_t log_level; + uint8_t init; +}; + +struct LoggerConfig* logger_get_configuration(); +void log_setup(char* progname, char* path); +void log_finalize(); +void log_init(struct CmdOptionParser* parser); +void write_log(const int level, const char* tag, const char *format, ...); + +#endif /* LOGGER_H_ */ + + diff --git a/src/iccpd/include/mlacp_fsm.h b/src/iccpd/include/mlacp_fsm.h new file mode 100644 index 000000000000..b89d21b780a1 --- /dev/null +++ b/src/iccpd/include/mlacp_fsm.h @@ -0,0 +1,102 @@ +/* +* mlacp_fsm.h +* mLACP finite state machine handler. +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef _MLACP_FSM_H +#define _MLACP_FSM_H + +#include "../include/port.h" + +#define MLCAP_SYNC_PHY_DEV_SEC 1 /*every 1 sec*/ + +#define MLACP(csm_ptr) (csm_ptr->app_csm.mlacp) + +struct CSM; + +enum MLACP_APP_STATE { + MLACP_STATE_INIT, + MLACP_STATE_STAGE1, + MLACP_STATE_STAGE2, + MLACP_STATE_EXCHANGE, + MLACP_STATE_ERROR, +}; + +typedef enum MLACP_APP_STATE MLACP_APP_STATE_E; + +/* for sender only*/ +enum MLACP_SYNC_STATE { + MLACP_SYNC_SYSCONF=0, + MLACP_SYNC_AGGCONF, + MLACP_SYNC_AGGSTATE, + MLACP_SYNC_AGGINFO, + MLACP_SYNC_PEERLINKINFO, + MLACP_SYNC_ARP_INFO, + MLACP_SYNC_DONE, +}; + +typedef enum MLACP_SYNC_STATE MLACP_SYNC_STATE_E; + +struct Remote_System { + uint8_t system_id[ETHER_ADDR_LEN]; + uint16_t system_priority; + uint32_t node_id; +}; + +struct mLACP { + int id; + int sync_req_num; + + MLACP_APP_STATE_E current_state; + MLACP_SYNC_STATE_E sync_state; + + uint8_t wait_for_sync_data; + uint8_t need_to_sync; + uint8_t node_id; + uint8_t system_id[ETHER_ADDR_LEN]; + uint16_t system_priority; + uint8_t system_config_changed; + + struct Remote_System remote_system; + const char* error_msg; + TAILQ_HEAD(mlacp_msg_list, Msg) mlacp_msg_list; + TAILQ_HEAD(arp_msg_list, Msg) arp_msg_list; + TAILQ_HEAD(arp_info_list, Msg) arp_list; + TAILQ_HEAD(mac_msg_list, Msg) mac_msg_list; + TAILQ_HEAD(mac_info_list, Msg) mac_list; + + LIST_HEAD(lif_list, LocalInterface) lif_list; + LIST_HEAD(lif_purge_list, LocalInterface) lif_purge_list; + LIST_HEAD(pif_list, PeerInterface) pif_list; +}; + +void mlacp_init(struct CSM* csm, int all); +void mlacp_finalize(struct CSM* csm); +void mlacp_fsm_transit(struct CSM* csm); +void mlacp_enqueue_msg(struct CSM*, struct Msg*); +struct Msg* mlacp_dequeue_msg(struct CSM*); + +/* from app_csm*/ +extern int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* local_if); +extern int mlacp_unbind_local_if(struct LocalInterface* local_if); + +#endif /* _MLACP_HANDLER_H */ diff --git a/src/iccpd/include/mlacp_link_handler.h b/src/iccpd/include/mlacp_link_handler.h new file mode 100644 index 000000000000..573ba1529720 --- /dev/null +++ b/src/iccpd/include/mlacp_link_handler.h @@ -0,0 +1,51 @@ +/* +* mlacp_link_handler.h +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef __MLACP_LINK_HANDLER__ +#define __MLACP_LINK_HANDLER__ + +#include "../include/iccp_csm.h" + +/***************************************** + * Link Handler + * + * ***************************************/ +void mlacp_portchannel_state_handler(struct CSM* csm, struct LocalInterface* local_if, int po_state); +void mlacp_peerlink_conn_handler(struct CSM* csm); +void mlacp_peerlink_disconn_handler(struct CSM* csm); +void update_stp_peer_link(struct CSM *csm, struct PeerInterface *peer_if, int po_state, int new_create); +void update_peerlink_isolate_from_pif(struct CSM *csm, struct PeerInterface *pif, int po_state, int new_create); +void mlacp_mlag_link_add_handler(struct CSM *csm, struct LocalInterface *lif); +void mlacp_mlag_link_del_handler(struct CSM *csm, struct LocalInterface *lif); +void set_peerlink_mlag_port_learn (struct LocalInterface *lif, int enable); +void peerlink_port_isolate_cleanup(struct CSM* csm); +void update_peerlink_isolate_from_all_csm_lif (struct CSM* csm); + +int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac); +int mlacp_fsm_arp_del(char *ifname, uint32_t ip); + +extern int mclagd_ctl_sock_create(); +extern int mclagd_ctl_sock_accept(int fd); +extern int mclagd_ctl_interactive_process(int client_fd); +int set_nonblocking(int fd); +char *show_ip_str(uint32_t ipv4_addr); +#endif diff --git a/src/iccpd/include/mlacp_sync_prepare.h b/src/iccpd/include/mlacp_sync_prepare.h new file mode 100644 index 000000000000..107d30742d7d --- /dev/null +++ b/src/iccpd/include/mlacp_sync_prepare.h @@ -0,0 +1,54 @@ +/* +* mlacp_sync_prepare.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef __MLACP_SYNC_PREPARE__ +#define __MLACP_SYNC_PREPARE__ + +struct CSM; +/***************************************** + * Tool Function + * + * ***************************************/ + void update_system_id(struct CSM* csm); + +/***************************************** + * LACP Sync + * + * ***************************************/ +int mlacp_sync_with_kernel_callback(); + +/***************************************** + * MLACP Sync + * + * ***************************************/ +int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_buf_size); +int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end); +int mlacp_prepare_for_sys_config(struct CSM* csm,char* buf, size_t max_buf_size); +int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg); +int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg); +int mlacp_prepare_for_heartbeat(struct CSM* csm,char* buf, size_t max_buf_size); +int mlacp_prepare_for_Aggport_state(struct CSM* csm,char* buf, size_t max_buf_size, struct LocalInterface* local_if); +int mlacp_prepare_for_Aggport_config(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* lif, int purge_flag); +int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* port_channel); + +#endif \ No newline at end of file diff --git a/src/iccpd/include/mlacp_sync_update.h b/src/iccpd/include/mlacp_sync_update.h new file mode 100644 index 000000000000..e611a8e2eee2 --- /dev/null +++ b/src/iccpd/include/mlacp_sync_update.h @@ -0,0 +1,45 @@ +/* +* +* mlacp_sync_update.h +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef __MLACP_SYNC_UPDATE__ +#define __MLACP_SYNC_UPDATE__ + +#include "iccp_csm.h" +#include "mlacp_tlv.h" + +/***************************************** + * FSM Sync Update API + * + * ***************************************/ +int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV* tlv); + +int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv); + +int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv); + +int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv); + +void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg); + +int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf); +#endif \ No newline at end of file diff --git a/src/iccpd/include/mlacp_tlv.h b/src/iccpd/include/mlacp_tlv.h new file mode 100644 index 000000000000..ad7640e3a839 --- /dev/null +++ b/src/iccpd/include/mlacp_tlv.h @@ -0,0 +1,413 @@ +/* +* mlacp_tlv.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef MLACP_TLV_H_ +#define MLACP_TLV_H_ + +#include + +#include "../include/msg_format.h" +#include "../include/port.h" + +#define MLACP_SYSCONF_NODEID_MSB_MASK 0x80 +#define MLACP_SYSCONF_NODEID_NODEID_MASK 0x70 +#define MLACP_SYSCONF_NODEID_FREE_MASK 0x0F + +/* +* RFC 7275 +* 7.2.3. mLACP System Config TLV +* [Page 51] +*/ +struct mLACPSysConfigTLV { + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.3.2. */ + uint8_t sys_id[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.3.2. */ + uint16_t sys_priority; + /* + * RFC 7275 + * 7.2.3. mLACP System Config TLV + * [Page 51] + */ + uint8_t node_id; +}__attribute__ ((packed)); + +typedef struct mLACPSysConfigTLV mLACPSysConfigTLV; + +/* +* RFC 7275 +* 7.2.4. mLACP Aggregator Config TLV +* [Page 52] +* NOTE: In this project, Aggregator configuration and state TLV is not support. +*/ +struct mLACPAggConfigTLV { + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ + uint8_t ro_id[8]; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ + uint8_t mac_addr[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ + uint16_t member_ports_priority; + uint8_t flags; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 54] + */ + uint8_t agg_name_len; + char agg_name[MAX_L_PORT_NAME]; +}__attribute__ ((packed)); + +typedef struct mLACPAggConfigTLV mLACPAggConfigTLV; + +/* +* RFC 7275 +* 7.2.4. mLACP Port Config TLV +* [Page 54] +*/ +struct mLACPPortConfigTLV { + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t port_num; + /* + * RFC 7275 + * 7.2.5. mLACP Port Config TLV + * [Page 55] + */ + uint8_t mac_addr[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t port_priority; + /* IF-MIB [RFC2863] */ + uint32_t port_speed; + /* + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 55] + */ + uint8_t flags; + /* + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 56] + */ + uint8_t port_name_len; + /* IF-MIB [RFC2863] */ + char port_name[MAX_L_PORT_NAME]; + + /* NOS */ + uint8_t orphan; + uint8_t l3_mode; +}__attribute__ ((packed)); + +typedef struct mLACPPortConfigTLV mLACPPortConfigTLV; + +/* +* RFC 7275 +* 7.2.6. mLACP Port Priority TLV +* [Page 56] +*/ +struct mLACPPortPriorityTLV { + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.6. mLACP Port Priority TLV + * [Page 57] + */ + uint16_t op_code; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t port_num; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t last_port_priority; + uint16_t current_port_priority; +}__attribute__ ((packed)); + +typedef struct mLACPPortPriorityTLV mLACPPortPriorityTLV; + +/* +* RFC 7275 +* 7.2.7. mLACP Port State TLV +* [Page 58] +*/ +struct mLACPPortStateTLV { + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.4.2.2, item r. */ + uint8_t partner_sys_id[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.4.2.2, item q. */ + uint16_t partner_sys_priority; + /* [IEEE-802.1AX], Section 5.4.2.2, item u. */ + uint16_t partner_port_num; + /* [IEEE-802.1AX], Section 5.4.2.2, item t. */ + uint16_t partner_port_priority; + /* [IEEE-802.1AX], Section 5.4.2.2, item s. */ + uint16_t partner_key; + /* [IEEE-802.1AX], Section 5.4.2.2, item v. */ + uint8_t partner_state; + /* [IEEE-802.1AX], Section 5.4.2.2, item m. */ + uint8_t actor_state; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t actor_port_num; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* [IEEE-802.1AX], Section 5.4.8 */ + uint8_t selected; + /* + * RFC 7275 + * 7.2.7. mLACP Port State TLV + * [Page 60] + */ + uint8_t port_state; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + + /* NOS */ + uint8_t orphan; + uint16_t port_id; + uint8_t l3_mode; + uint8_t is_peer_link; +}__attribute__ ((packed)); + +typedef struct mLACPPortStateTLV mLACPPortStateTLV; + +/* +* RFC 7275 +* 7.2.8. mLACP Aggregator State TLV +* [Page 60] +* NOTE: In this project, Aggregator configuration and state TLV is not support. +*/ +struct mLACPAggPortStateTLV { + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.4.2.2, item r. */ + uint8_t partner_sys_id[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.4.2.2, item q. */ + uint16_t partner_sys_priority; + /* [IEEE-802.1AX], Section 5.4.2.2, item s. */ + uint16_t partner_key; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* + * RFC 7275 + * 7.2.8. mLACP Aggregator State TLV + * [Page 61] + */ + uint8_t agg_state; +}__attribute__ ((packed)); + +typedef struct mLACPAggPortStateTLV mLACPAggPortStateTLV; + +/* +* RFC 7275 +* 7.2.9. mLACP Synchronization Request TLV +* [Page 61] +*/ +struct mLACPSyncReqTLV { + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 62] + */ + uint16_t req_num; + uint16_t c_bit :1; + /* + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 63] + */ + uint16_t s_bit :1; + uint16_t req_type :14; + /* [IEEE-802.1AX], Section 5.3.4. */ + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t port_num_agg_id; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; +}__attribute__ ((packed)); + +typedef struct mLACPSyncReqTLV mLACPSyncReqTLV; + +/* +* RFC 7275 +* 7.2.10. mLACP Synchronization Data TLV +* [Page 63] +*/ +struct mLACPSyncDataTLV { + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.10. mLACP Synchronization Data TLV + * [Page 64] + */ + uint16_t req_num; + uint16_t flags; +}__attribute__ ((packed)); + +typedef struct mLACPSyncDataTLV mLACPSyncDataTLV; + +/* VLAN Information TLV*/ +struct mLACPVLANData { + uint16_t vlan_id; +}__attribute__ ((packed)); + +/* +* Port Channel Information TLV +*/ +struct mLACPPortChannelInfoTLV { + ICCParameter icc_parameter; + uint16_t agg_id; + char if_name[MAX_L_PORT_NAME]; + uint8_t if_name_len; + uint8_t l3_mode; + uint32_t ipv4_addr; + uint16_t orphan; + uint16_t po_id; + uint16_t num_of_vlan_id; + struct mLACPVLANData vlanData[0]; +}__attribute__ ((packed)); + +typedef struct mLACPPortChannelInfoTLV mLACPPortChannelInfoTLV; + +/* +* Port PeerLink Information TLV +*/ +struct mLACPPeerLinkInfoTLV { + ICCParameter icc_parameter; + char if_name[MAX_L_PORT_NAME]; + uint8_t port_type; +}__attribute__ ((packed)); + +typedef struct mLACPPeerLinkInfoTLV mLACPPeerLinkInfoTLV; + + +struct mLACPVLANInfoTLV { + ICCParameter icc_parameter; + uint16_t id; /* Local Interface ID, not VLAN ID */ + uint16_t num_of_vlan_id; + struct mLACPVLANData vlanData[0]; +}__attribute__ ((packed)); + +/* +* MAC Information TLV +*/ +struct mLACPMACInfoTLV { + ICCParameter icc_parameter; + uint8_t type;/*add or del*/ + char mac_str[32]; + uint16_t vid; + /*Current if name that set in chip*/ + char ifname[MAX_L_PORT_NAME]; +}__attribute__ ((packed)); + +/* +* ARP Information TLV +*/ +struct mLACPARPInfoTLV { + ICCParameter icc_parameter; + /* Local Interface ID */ + uint8_t type; + char ifname[MAX_L_PORT_NAME]; + uint32_t ipv4_addr; + uint8_t mac_addr[ETHER_ADDR_LEN]; +}__attribute__ ((packed)); + +/* +* NOS: STP Information TLV +*/ +struct stp_msg_s; +struct mLACPSTPInfoTLV { + ICCParameter icc_parameter; + uint8_t stp_msg[0]; +}__attribute__ ((packed)); + +/* +* NOS: Heartbeat +*/ +struct mLACPHeartbeatTLV { + ICCParameter icc_parameter; + uint8_t heartbeat; +}__attribute__ ((packed)); + +enum ARP_OP_TYPE { + ARP_SYNC_LIF, + ARP_SYNC_ADD, + ARP_SYNC_DEL, +}; + +struct ARPMsg { + uint8_t op_type; + char ifname[MAX_L_PORT_NAME]; + uint32_t ipv4_addr; + uint8_t mac_addr[ETHER_ADDR_LEN]; + time_t update_time; +}; + +enum MAC_AGE_TYPE { + MAC_AGE_LOCAL = 1,/*MAC in local switch is ageout*/ + MAC_AGE_PEER = 2, /*MAC in peer switch is ageout*/ +}; + +enum MAC_OP_TYPE { + MAC_SYNC_ADD = 1, + MAC_SYNC_DEL = 2, + MAC_SYNC_ACK = 4, +}; + +enum MAC_TYPE { + MAC_TYPE_STATIC = 1, + MAC_TYPE_DYNAMIC = 2, +}; + +struct MACMsg { + uint8_t op_type;/*add or del*/ + uint8_t fdb_type;/*static or dynamic*/ + char mac_str[32]; + uint16_t vid; + /*Current if name that set in chip*/ + char ifname[MAX_L_PORT_NAME]; + /*if we set the mac to peer-link, origin_ifname store the + original if name that learned from chip*/ + char origin_ifname[MAX_L_PORT_NAME]; + uint8_t age_flag;/*local or peer is age?*/ +}; + +#endif /* MLACP_TLV_H_ */ diff --git a/src/iccpd/include/msg_format.h b/src/iccpd/include/msg_format.h new file mode 100644 index 000000000000..21a338be4d66 --- /dev/null +++ b/src/iccpd/include/msg_format.h @@ -0,0 +1,427 @@ +/* +* msg_format.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef MSG_FORMAT_H_ +#define MSG_FORMAT_H_ +#include +#include + + +#define MAX_MSG_LOG_SIZE 128 + +/* + * RFC 5561 + * 4. Capability Message + * [Page 7] + */ +#define MSG_T_CAPABILITY 0x0202 + +/* + * RFC 7275 + * 6.1.1. ICC Header - Message Length + * [Page 25] + * 2-octet integer specifying the total length of this message in octets, + * excluding the "U-bit", "Message Type", and "Length" fields. + */ +#define MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS 4 + +/* + * RFC 7275 + * 12.1. Message Type Name Space + * [Page 79] + */ +#define MSG_T_RG_CONNECT 0x0700 +#define MSG_T_RG_DISCONNECT 0x0701 +#define MSG_T_NOTIFICATION 0x0702 +#define MSG_T_RG_APP_DATA 0x0703 + +/* + * RFC 7275 + * 12.2. TLV Type Name Space + * [Page 79] + */ +#define TLV_T_ICCP_CAPABILITY 0x0700 +#define TLV_L_ICCP_CAPABILITY 0x4 + +/* + * RFC 7275 + * 12.3. ICC RG Parameter Type Space + * [Page 80] + */ +#define TLV_T_ICC_SENDER_NAME 0x0001 +#define MAX_L_ICC_SENDER_NAME 80 +#define TLV_T_NAK 0x0002 +#define TLV_T_REQUESTED_PROTOCOL_VER 0x0003 +#define TLV_T_DISCONNECT_CODE 0x0004 +#define TLV_L_DISCONNECT_CODE 0x4 +#define TLV_T_ICC_RG_ID 0x0005 +#define TLV_L_ICC_RG_ID 0x4 + +#define TLV_T_MLACP_CONNECT 0x0030 +#define TLV_T_MLACP_DISCONNECT 0x0031 +#define TLV_T_MLACP_SYSTEM_CONFIG 0x0032 +#define TLV_T_MLACP_PORT_CONFIG 0x0033//no support +#define TLV_T_MLACP_PORT_PRIORITY 0x0034//no support +#define TLV_T_MLACP_PORT_STATE 0x0035//no support +#define TLV_T_MLACP_AGGREGATOR_CONFIG 0x0036 +#define TLV_T_MLACP_AGGREGATOR_STATE 0x0037 +#define TLV_T_MLACP_SYNC_REQUEST 0x0038 +#define TLV_T_MLACP_SYNC_DATA 0x0039 +#define TLV_T_MLACP_HEARTBEAT 0x003A +#define TLV_T_MLACP_DISCONNECT_CAUSE 0x003B //not yet + +/* Self define Feature */ +#define TLV_T_MLACP_ORPHAN_PORT 0x1033 //not yet +#define TLV_T_MLACP_PORT_CHANNEL_INFO 0x1034 +#define TLV_T_MLACP_PEERLINK_INFO 0x1035 +#define TLV_T_MLACP_ARP_INFO 0x1036 +#define TLV_T_MLACP_STP_INFO 0x1037//no support +#define TLV_T_MLACP_MAC_INFO 0x1038 + +#define TLV_T_MLACP_LIST_END 0x1039 //list end + +/* Debug */ +static char* get_tlv_type_string(int type) +{ + switch(type) + { + case TLV_T_ICCP_CAPABILITY: + return "TLV_T_ICCP_CAPABILITY"; + case TLV_T_ICC_SENDER_NAME: + return "TLV_T_ICC_SENDER_NAME"; + case TLV_T_NAK: + return "TLV_T_NAK"; + case TLV_T_REQUESTED_PROTOCOL_VER: + return "TLV_T_REQUESTED_PROTOCOL_VER"; + case TLV_T_DISCONNECT_CODE: + return "TLV_T_DISCONNECT_CODE"; + case TLV_T_ICC_RG_ID: + return "TLV_T_ICC_RG_ID"; + case TLV_T_MLACP_CONNECT: + return "TLV_T_MLACP_CONNECT"; + case TLV_T_MLACP_DISCONNECT: + return "TLV_T_MLACP_DISCONNECT"; + case TLV_T_MLACP_SYSTEM_CONFIG: + return "TLV_T_MLACP_SYSTEM_CONFIG"; + case TLV_T_MLACP_PORT_CONFIG: + return "TLV_T_MLACP_PORT_CONFIG"; + case TLV_T_MLACP_PORT_PRIORITY: + return "TLV_T_MLACP_PORT_PRIORITY"; + case TLV_T_MLACP_PORT_STATE: + return "TLV_T_MLACP_PORT_STATE"; + case TLV_T_MLACP_AGGREGATOR_CONFIG: + return "TLV_T_MLACP_AGGREGATOR_CONFIG"; + case TLV_T_MLACP_AGGREGATOR_STATE: + return "TLV_T_MLACP_AGGREGATOR_STATE"; + case TLV_T_MLACP_SYNC_REQUEST: + return "TLV_T_MLACP_SYNC_REQUEST"; + case TLV_T_MLACP_SYNC_DATA: + return "TLV_T_MLACP_SYNC_DATA"; + case TLV_T_MLACP_HEARTBEAT: + return "TLV_T_MLACP_HEARTBEAT"; + case TLV_T_MLACP_DISCONNECT_CAUSE: + return "TLV_T_MLACP_DISCONNECT_CAUSE"; + + /* NOS Feature */ + case TLV_T_MLACP_ORPHAN_PORT: + return "TLV_T_MLACP_ORPHAN_PORT"; + case TLV_T_MLACP_PORT_CHANNEL_INFO: + return "TLV_T_MLACP_PORT_CHANNEL_INFO"; + case TLV_T_MLACP_PEERLINK_INFO: + return "TLV_T_MLACP_PEERLINK_INFO"; + case TLV_T_MLACP_ARP_INFO: + return "TLV_T_MLACP_ARP_INFO"; + case TLV_T_MLACP_MAC_INFO: + return "TLV_T_MLACP_MAC_INFO"; + case TLV_T_MLACP_STP_INFO: + return "TLV_T_MLACP_STP_INFO"; + } + return "UNKNOWN"; +} + +/* + * RFC 7275 + * 12.4. Status Code Name Space + * [Page 81] + */ +#define STATUS_CODE_U_ICCP_RG 0x00010001 +#define STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED 0x00010002 +#define STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED 0x00010003 +#define STATUS_CODE_ICCP_APP_NOT_IN_RG 0x00010004 +#define STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER 0x00010005 +#define STATUS_CODE_ICCP_REJECTED_MSG 0x00010006 +#define STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED 0x00010007 +#define STATUS_CODE_ICCP_RG_REMOVED 0x00010010 +#define STATUS_CODE_ICCP_APP_REMOVED_FROM_RG 0x00010011 + + +/* Debug */ +static char* get_status_string(int status) +{ + switch(status) + { + case STATUS_CODE_U_ICCP_RG: + return "Unknown ICCP RG"; + case STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED: + return "ICCP Connection Count Exceeded"; + case STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED: + return "ICCP Application Connection Count Exceede"; + case STATUS_CODE_ICCP_APP_NOT_IN_RG: + return "ICCP Application not in RG"; + case STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER: + return "Incompatible ICCP Protocol Version"; + case STATUS_CODE_ICCP_REJECTED_MSG: + return "ICCP Rejected Message"; + case STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED: + return "ICCP Administratively Disabled"; + case STATUS_CODE_ICCP_RG_REMOVED: + return "ICCP RG Removed"; + case STATUS_CODE_ICCP_APP_REMOVED_FROM_RG: + return "ICCP Application Removed from RG"; + } + return "UNKNOWN"; +} +/* + * RFC 5036 + * 3.5. LDP Messages + * [Page 44] + */ +struct LDPHdr { + uint16_t u_bit :1; + uint16_t msg_type :15; + uint16_t msg_len; + uint32_t msg_id; +}__attribute__ ((packed)); + +typedef struct LDPHdr LDPHdr; + +/* + * RFC 7275 + * 6.1.1. ICC Header + * [Page 24] + */ +struct ICCRGIDTLV { + uint16_t type; + uint16_t len; + uint32_t icc_rg_id; +}__attribute__ ((packed)); + +typedef struct ICCRGIDTLV ICCRGIDTLV; + +struct ICCHdr { + LDPHdr ldp_hdr; + ICCRGIDTLV icc_rg_id_tlv; +}__attribute__ ((packed)); + +typedef struct ICCHdr ICCHdr; + +/* + * RFC 7275 + * 6.1.2. ICC Parameter Encoding + * [Page 26] + */ +struct ICCParameter { + uint16_t u_bit :1; + uint16_t f_bit :1; + uint16_t type :14; + uint16_t len; +}__attribute__ ((packed)); + +typedef struct ICCParameter ICCParameter; + +/* + * RFC 7275 + * 6.2.1. ICC Sender Name TLV + * [Page 28] + */ +struct ICCSenderNameTLV { + ICCParameter icc_parameter; + char sender_name[MAX_L_ICC_SENDER_NAME]; +}__attribute__ ((packed)); + +typedef struct ICCSenderNameTLV ICCSenderNameTLV; + +/* + * RFC 7275 + * 6.3. RG Disconnect Message + * [Page 29] + */ +struct DisconnectCodeTLV { + ICCParameter icc_parameter; + uint32_t iccp_status_code; +}__attribute__ ((packed)); + +typedef struct DisconnectCodeTLV DisconnectCodeTLV; + +/* + * RFC 7275 + * 6.4.1. Notification Message TLVs + * [Page 32] + */ +struct NAKTLV { + ICCParameter icc_parameter; + uint32_t iccp_status_code; + uint32_t rejected_msg_id; +}__attribute__ ((packed)); + +typedef struct NAKTLV NAKTLV; + +/* + * RFC 7275 + * 6.4.1. Notification Message TLVs + * [Page 34] + */ +struct RequestedProtocolVerTLV { + ICCParameter icc_parameter; + uint16_t connection_ref; + uint16_t requested_ver; +}__attribute__ ((packed)); + +typedef struct RequestedProtocolVerTLV RequestedProtocolVerTLV; + +/* + * RFC 7275 + * 8. LDP Capability Negotiation + * [Page 65] + */ +struct LDPICCPCapabilityTLV { + ICCParameter icc_parameter; + uint16_t s_bit :1; + uint16_t reserved :15; + uint8_t major_ver; + uint8_t minior_ver; +}__attribute__ ((packed)); + +typedef struct LDPICCPCapabilityTLV LDPICCPCapabilityTLV; + +/* + * RFC 7275 + * 7.2.1. mLACP Connect TLV + * [Page 47] + */ +struct AppConnectTLV { + ICCParameter icc_parameter; + uint16_t protocol_version; + uint16_t a_bit :1; + uint16_t reserved :15; + + /* Optional Sub-TLVs */ + /* No optional sub-TLVs in this version */ +}__attribute__ ((packed)); + +typedef struct AppConnectTLV AppConnectTLV; + +/* + * RFC 7275 + * 7.2.2. mLACP Disconnect TLV + * [Page 48] + */ +struct AppDisconnectTLV { + ICCParameter icc_parameter; + + /* Optional Sub-TLVs */ + /* mLACP Disconnect Cause TLV */ +}__attribute__ ((packed)); + +typedef struct AppDisconnectTLV AppDisconnectTLV; + +/* + * RFC 7275 + * 7.2.2.1. mLACP Disconnect Cause TLV + * [Page 49] + */ +struct AppDisconnectCauseTLV { + ICCParameter iccp_parameter; + + /* Disconnect Cause String */ + char cause_string[0]; /* Trick */ +}__attribute__ ((packed)); + +/*syncd send msg type to iccpd*/ +typedef enum mclag_syncd_msg_type_e_ { + MCLAG_SYNCD_MSG_TYPE_NONE = 0, + MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1 +}mclag_syncd_msg_type_e; + +typedef enum mclag_msg_type_e_ { + MCLAG_MSG_TYPE_NONE = 0, + MCLAG_MSG_TYPE_PORT_ISOLATE = 1, + MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE = 2, + MCLAG_MSG_TYPE_FLUSH_FDB = 3, + MCLAG_MSG_TYPE_SET_MAC = 4, + MCLAG_MSG_TYPE_SET_FDB = 5, + MCLAG_MSG_TYPE_GET_FDB_CHANGES = 20 +}mclag_msg_type_e; + + +typedef enum mclag_sub_option_type_e_ { + MCLAG_SUB_OPTION_TYPE_NONE = 0, + MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC = 1, + MCLAG_SUB_OPTION_TYPE_ISOLATE_DST = 2, + MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE = 3, + MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4, + MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC = 5, + MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6 +} mclag_sub_option_type_e; + + +struct IccpSyncdHDr { + uint8_t ver; + uint8_t type; + uint16_t len; +}; + +typedef struct mclag_sub_option_hdr_t_ { + + uint8_t op_type; + + /* + * Length of option value, not including the header. + */ + uint16_t op_len; + uint8_t data[]; +}mclag_sub_option_hdr_t; + +struct mclag_fdb_info +{ + unsigned char mac[32]; + unsigned int vid; + unsigned char port_name[32]; + short type;/*dynamic or static*/ + short op_type;/*add or del*/ +}; + +/* For storing message log: For Notification TLV */ +struct MsgTypeSet { + uint32_t msg_id; + uint16_t type; + uint16_t tlv; + +}; + +struct MsgLog { + struct MsgTypeSet msg[MAX_MSG_LOG_SIZE]; + uint32_t end_index; +}; + +#endif /* MSG_FORMAT_H_ */ diff --git a/src/iccpd/include/port.h b/src/iccpd/include/port.h new file mode 100644 index 000000000000..78743d0a4e48 --- /dev/null +++ b/src/iccpd/include/port.h @@ -0,0 +1,149 @@ +/* +* port.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef PORT_H_ +#define PORT_H_ + +#include +#include +#include + +#define ETHER_ADDR_LEN 6 +/* +* RFC 7275 +* 7.2.4. mLACP Port Config TLV +* [Page 56] +*/ +#define MAX_L_PORT_NAME 20 + +/* defined in RFC 7275 - 7.2.7 (p.59) */ +#define PORT_STATE_UP 0x00 +#define PORT_STATE_DOWN 0x01 +#define PORT_STATE_ADMIN_DOWN 0x02 +#define PORT_STATE_TEST 0x03 + +/* Interface Type */ +#define IF_T_UNKNOW -1 +#define IF_T_PORT 0 +#define IF_T_PORT_CHANNEL 1 +#define IF_T_VLAN 2 + +typedef struct { + char *ifname; + int type; +} itf_type_t; + +struct If_info{ + char name[MAX_L_PORT_NAME]; + LIST_ENTRY(If_info) csm_next; +}; + +struct VLAN_ID { + uint16_t vid; + uint16_t vlan_removed; + struct LocalInterface* vlan_itf; /* loacl vlan interface */ + LIST_ENTRY(VLAN_ID) port_next; +}; + +struct PeerInterface { + int ifindex; + int type; + char name[MAX_L_PORT_NAME]; + + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint8_t state; + uint32_t ipv4_addr; + + uint8_t l3_mode; + uint8_t is_peer_link; + int po_id; + uint8_t po_active; + + struct CSM* csm; + + LIST_ENTRY(PeerInterface) mlacp_next; + LIST_HEAD(peer_vlan_list, VLAN_ID) vlan_list; +}; + +struct LocalInterface { + int ifindex; + int type; + char name[MAX_L_PORT_NAME]; + + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint8_t mac_addr_ori[ETHER_ADDR_LEN]; + uint8_t state; + uint32_t ipv4_addr; + uint8_t prefixlen; + + uint8_t l3_mode; + uint8_t is_peer_link; + char portchannel_member_buf[512]; + uint8_t is_arp_accept; + int po_id; /* Port Channel ID */ + uint8_t po_active; /* Port Channel is in active status? */ + int mlacp_state; /* Record mlacp state */ + uint8_t isolate_to_peer_link; + + struct CSM* csm; + + uint8_t changed; + uint8_t port_config_sync; + + LIST_HEAD(local_vlan_list, VLAN_ID) vlan_list; + + LIST_ENTRY(LocalInterface) system_next; + LIST_ENTRY(LocalInterface) system_purge_next; + LIST_ENTRY(LocalInterface) mlacp_next; + LIST_ENTRY(LocalInterface) mlacp_purge_next; +}; + +struct LocalInterface* local_if_create(int ifindex, char* ifname, int type); +struct LocalInterface* local_if_find_by_name(const char* ifname); +struct LocalInterface* local_if_find_by_ifindex(int ifindex); +struct LocalInterface* local_if_find_by_po_id(int po_id); + +void local_if_destroy(char *ifname); +void local_if_change_flag_clear(void); +void local_if_purge_clear(void); +int local_if_is_l3_mode(struct LocalInterface* local_if); + +void local_if_init(struct LocalInterface*); +void local_if_finalize(struct LocalInterface*); + +void ether_mac_set_addr_with_if_name(char* name, uint8_t* mac); + +struct PeerInterface* peer_if_create(struct CSM* csm, int peer_if_number, int type); +struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name); + +void peer_if_destroy(struct PeerInterface* pif); + +/* VLAN manipulation */ +int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid); +void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid); +void local_if_del_all_vlan(struct LocalInterface* lif); + +/* ARP manipulation */ +int set_sys_arp_accept_flag(char* ifname, int flag); + +#endif /* PORT_H_ */ diff --git a/src/iccpd/include/scheduler.h b/src/iccpd/include/scheduler.h new file mode 100644 index 000000000000..156b82247242 --- /dev/null +++ b/src/iccpd/include/scheduler.h @@ -0,0 +1,58 @@ +/* +* scheduler.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef SCHEDULER_H_ +#define SCHEDULER_H_ + +#include + +#include +#include +#include + +#include +#include +#include + +struct CSM; + +#define CONNECT_INTERVAL_SEC 1 +#define CONNECT_TIMEOUT_MSEC 100 +#define HEARTBEAT_TIMEOUT_SEC 15 +#define TRANSIT_INTERVAL_SEC 1 +#define EPOLL_TIMEOUT_MSEC 100 + +int scheduler_prepare_session(struct CSM*); +int scheduler_check_csm_config(struct CSM*); +int scheduler_unregister_sock_read_event_callback(struct CSM*); +void scheduler_session_disconnect_handler(struct CSM*); +void scheduler_init(); +void scheduler_finalize(); +void scheduler_loop(); +void scheduler_start(); +void scheduler_server_sock_init(); +int scheduler_csm_read_callback(struct CSM* csm) ; +int iccp_get_server_sock_fd(); +int scheduler_server_accept(); + +#endif /* SCHEDULER_H_ */ diff --git a/src/iccpd/include/system.h b/src/iccpd/include/system.h new file mode 100644 index 000000000000..f28236e1c238 --- /dev/null +++ b/src/iccpd/include/system.h @@ -0,0 +1,83 @@ +/* +* system.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef SYSTEM_H_ +#define SYSTEM_H_ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "../include/port.h" + +struct CSM; + +struct System { + int server_fd;/* Peer-Link Socket*/ + int sync_fd; + int sync_ctrl_fd; + int arp_receive_fd; + int epoll_fd; + + struct nl_sock * genric_sock; + int genric_sock_seq; + int family; + struct nl_sock * route_sock; + int route_sock_seq; + struct nl_sock * genric_event_sock; + struct nl_sock * route_event_sock; + + /* Info List*/ + LIST_HEAD(csm_list, CSM) csm_list; + LIST_HEAD(lif_all_list, LocalInterface) lif_list; + LIST_HEAD(lif_purge_all_list, LocalInterface) lif_purge_list; + + /* Settings */ + char* log_file_path; + char* cmd_file_path; + char* config_file_path; + char* mclagdctl_file_path; + int pid_file_fd; + int telnet_port; + fd_set readfd; /*record socket need to listen*/ + int readfd_count; + time_t csm_trans_time; + int need_sync_team_again; + int need_sync_netlink_again; +}; + +struct CSM* system_create_csm(); +struct CSM* system_get_csm_by_peer_ip(const char*); +struct CSM* system_get_csm_by_mlacp_id(int id); +struct System* system_get_instance(); +void system_finalize(); +void system_init(struct System*); + +#endif /* SYSTEM_H_ */ diff --git a/src/iccpd/src/Makefile b/src/iccpd/src/Makefile new file mode 100644 index 000000000000..5e8cebc703c0 --- /dev/null +++ b/src/iccpd/src/Makefile @@ -0,0 +1,55 @@ +LIBNL_CFLAGS = -I/usr/include/libnl3 +LIBNL_LIBS = -lnl-cli-3 -lnl-genl-3 -lnl-nf-3 -lnl-route-3 -lnl-3 + +CC = gcc +SOURCES = app_csm.c cmd_option.c iccp_cli.c iccp_cmd_show.c iccp_cmd.c \ +iccp_csm.c iccp_ifm.c iccp_main.c logger.c \ +port.c scheduler.c system.c iccp_consistency_check.c \ +mlacp_link_handler.c \ +mlacp_sync_prepare.c mlacp_sync_update.c\ +mlacp_fsm.c \ +iccp_netlink.c + +OBJECTS = app_csm.o cmd_option.o iccp_cli.o iccp_cmd_show.o iccp_cmd.o \ +iccp_csm.o iccp_ifm.o iccp_main.o logger.o \ +port.o scheduler.o system.o iccp_consistency_check.o\ +mlacp_link_handler.o \ +mlacp_sync_prepare.o mlacp_sync_update.o \ +mlacp_fsm.o \ +iccp_netlink.o + +HEADERS = ../include/app_csm.h ../include/cmd_option.h ../include/iccp_cli.h \ +../include/iccp_cmd_show.h \ +../include/iccp_csm.h ../include/iccp_ifm.h \ +../include/logger.h ../include/mlacp_fsm.h \ +../include/mlacp_tlv.h ../include/msg_format.h ../include/port.h \ +../include/scheduler.h ../include/system.h \ +../include/iccp_consistency_check.h ../include/route_info.h \ +../include/iccp_netlink.h + +//CFLAGS = -g -O2 -fstack-protector-strong -Wformat -Werror=format-security $(LIBNL_CFLAGS) -I../include/ +CFLAGS = -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -I../include/ $(LIBNL_CFLAGS) +LDFLAGS = $(LIBNL_LIBS) -lpthread +LDADD = $(LIBZEBRA_BIN) + +all: iccpd + +%.o: %.c $(HEADERS) + +iccpd: $(OBJECTS) + $(CC) -o ../iccpd $(OBJECTS) $(LDFLAGS) + +DEPS = $(patsubst %.o, %.d, $(OBJECTS)) + +-include $(DEPS) +%.d:%.c + @set -e; rm -f $@; \ + gcc -MM $(CPPFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + + + +.PHONY: clean +clean: + -rm -f $(OBJECTS) $(DEPS) ../iccpd diff --git a/src/iccpd/src/app_csm.c b/src/iccpd/src/app_csm.c new file mode 100644 index 000000000000..5e4ccf42c45e --- /dev/null +++ b/src/iccpd/src/app_csm.c @@ -0,0 +1,312 @@ +/* +* app_csm.c +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include + +#include "../include/iccp_csm.h" +#include "../include/logger.h" +#include "../include/scheduler.h" +#include "../include/system.h" + +/***************************************** +* Define +* +* ***************************************/ +#define APP_CSM_QUEUE_REINIT(list) \ + {\ + struct Msg* msg = NULL;\ + while (!TAILQ_EMPTY(&(list))) {\ + msg = TAILQ_FIRST(&(list));\ + TAILQ_REMOVE(&(list), msg, tail);\ + free(msg->buf);\ + free(msg);\ + }\ + TAILQ_INIT(&(list));\ + } + +/* Application State Machine instance initialization */ +void app_csm_init(struct CSM* csm, int all) +{ + if (csm == NULL ) + return; + + APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); + + if(all) + { + bzero(&(csm->app_csm), sizeof(struct AppCSM)); + APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); + } + + csm->app_csm.current_state = APP_NONEXISTENT; + csm->app_csm.rx_connect_msg_id = 0; + csm->app_csm.tx_connect_msg_id = 0; + csm->app_csm.invalid_msg_id = 0; + csm->app_csm.invalid_msg = 0; + csm->app_csm.nak_msg = 0; + + mlacp_init(csm, all); +} + +/* Application State Machine instance tear down */ +void app_csm_finalize(struct CSM* csm) +{ + mlacp_finalize(csm); +} + +/* Application State Machine Transition */ +void app_csm_transit(struct CSM* csm) +{ + if (csm == NULL ) + return; + + /* torn down event */ + if (csm->app_csm.current_state != APP_NONEXISTENT && csm->sock_fd <= 0) + { + csm->app_csm.current_state = APP_NONEXISTENT; + return; + } + + if(csm->app_csm.current_state != APP_OPERATIONAL && csm->current_state == ICCP_OPERATIONAL) + { + csm->app_csm.current_state = APP_OPERATIONAL; + } + + return; +} + +/* Add received message into application message list */ +void app_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + ICCParameter* param = NULL; + NAKTLV* naktlv = NULL; + int tlv = -1; + int i = 0; + + if (csm == NULL ) + { + if (msg != NULL ) + free(msg); + return; + } + if (msg == NULL ) + return; + + icc_hdr = (ICCHdr*) msg->buf; + param = (ICCParameter*) &msg->buf[sizeof(struct ICCHdr)]; + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + if(param->type > TLV_T_MLACP_CONNECT && param->type < TLV_T_MLACP_LIST_END) + mlacp_enqueue_msg(csm, msg); + else + TAILQ_INSERT_TAIL(&(csm->app_csm.app_msg_list), msg, tail); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + { + naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; + for(i=0; irejected_msg_id == csm->msg_log.msg[i].msg_id) + { + tlv = csm->msg_log.msg[i].tlv; + break; + } + } + + if(tlv > TLV_T_MLACP_CONNECT && tlv <= TLV_T_MLACP_MAC_INFO) + mlacp_enqueue_msg(csm, msg); + else + TAILQ_INSERT_TAIL(&(csm->app_csm.app_msg_list), msg, tail); + } + else + { + /* This packet is not for me, ignore it. */ + ICCPD_LOG_DEBUG(__FUNCTION__, "Ignore the packet with msg_type = %d", icc_hdr->ldp_hdr.msg_type); + } +} + +/* Get received message from message list */ +struct Msg* app_csm_dequeue_msg(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (!TAILQ_EMPTY(&(csm->app_csm.app_msg_list))) + { + msg = TAILQ_FIRST(&(csm->app_csm.app_msg_list)); + TAILQ_REMOVE(&(csm->app_csm.app_msg_list), msg, tail); + } + + return msg; +} + +/* APP NAK message handle function */ +int app_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + NAKTLV* naktlv = (NAKTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); + + ICCPD_LOG_DEBUG(__FUNCTION__, " Response NAK"); + memset(buf, 0, max_buf_size); + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_NOTIFICATION; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + naktlv->icc_parameter.u_bit = 0; + naktlv->icc_parameter.f_bit = 0; + naktlv->icc_parameter.type = TLV_T_NAK; + naktlv->icc_parameter.len = sizeof(NAKTLV) - 4; + + naktlv->iccp_status_code = STATUS_CODE_ICCP_REJECTED_MSG; + naktlv->rejected_msg_id = csm->app_csm.invalid_msg_id; + + return msg_len; +} + +int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) +{ + struct LocalInterface* lifp = NULL; + struct LocalInterface* lif_po = NULL; + + if (csm == NULL || lif == NULL) + return -1; + + if (lif->csm == csm) + return 0; + + /* remove purge from the csm*/ + do + { + LIST_FOREACH(lifp, &(MLACP(csm).lif_purge_list), mlacp_purge_next) + { + if (lifp == lif) + break; + } + if (lifp) + LIST_REMOVE(lifp, mlacp_purge_next); + } while (lifp); + + /* already join csm?*/ + LIST_FOREACH(lifp, &(MLACP(csm).lif_list), mlacp_next) + { + if (lifp == lif) + return 0; + } + + /* join another csm beofre? remove from csm*/ + if (lif->csm != NULL) + mlacp_unbind_local_if(lif); + + /* join new csm*/ + LIST_INSERT_HEAD(&(MLACP(csm).lif_list), lif, mlacp_next); + lif->csm = csm; + if (lif->type == IF_T_PORT_CHANNEL) lif->port_config_sync = 1; + + ICCPD_LOG_INFO(__FUNCTION__, "%s: MLACP bind on csm %p", lif->name, csm); + if (lif->type == IF_T_PORT_CHANNEL) + return 0; + + /* if join a po member, needs to check po joined also*/ + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type == IF_T_PORT_CHANNEL && lif_po->po_id == lif->po_id) + return 0; + } + + if (lif_po == NULL) + { + lif_po = local_if_find_by_po_id(lif->po_id); + if (lif_po == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, + "Failed to find port_channel instance for %d.", + lif->po_id); + return -1; + } + + lif_po->csm = csm; + LIST_INSERT_HEAD(&(MLACP(csm).lif_list), lif_po, mlacp_next); + lif_po->port_config_sync = 1; + ICCPD_LOG_INFO(__FUNCTION__, "Add port_channel %d into local_if_list in CSM %p.", lif->po_id, csm); + } + + return 0; +} + +int mlacp_unbind_local_if(struct LocalInterface* lif) +{ + if (lif == NULL ) + return -1; + + if (lif->csm == NULL ) + return 0; + + ICCPD_LOG_INFO(__FUNCTION__, "%s: MLACP un-bind from csm %p", lif->name, lif->csm); + LIST_REMOVE(lif, mlacp_next); + + if (MLACP(lif->csm).current_state == MLACP_STATE_EXCHANGE && lif->type == IF_T_PORT_CHANNEL) + LIST_INSERT_HEAD(&(MLACP(lif->csm).lif_purge_list), lif, mlacp_purge_next); + if (lif->type == IF_T_PORT) + lif->po_id = -1; + lif->csm = NULL; + + return 0; +} + +int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname) +{ + struct System* sys = NULL; + struct LocalInterface *lif_po = NULL; + + sys = system_get_instance(); + if(sys == NULL) + return 0; + + if (csm == NULL) + return 0; + + /* bind po first*/ + lif_po = local_if_find_by_name(ifname); + if (lif_po) + { + mlacp_bind_local_if(csm, lif_po); + iccp_get_port_member_list(lif_po); + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, + "%s: Failed to find a port instance .", + ifname); + return 0; + } + /* process link state handler after attaching it.*/ + + mlacp_mlag_link_add_handler(csm, lif_po); + + /*ICCPD_LOG_WARN(tag, "po%d active = %d\n", po_id, po_is_active);*/ + return 0; +} + diff --git a/src/iccpd/src/cmd_option.c b/src/iccpd/src/cmd_option.c new file mode 100644 index 000000000000..21be3ceebd59 --- /dev/null +++ b/src/iccpd/src/cmd_option.c @@ -0,0 +1,262 @@ +/* +* cmd_option.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include "../include/cmd_option.h" + +struct CmdOption* cmd_option_find(struct CmdOptionParser* parser, char* opt_name) +{ + struct CmdOption* opt = NULL; + + if (opt_name == NULL) + return NULL; + + LIST_FOREACH(opt, &(parser->option_list), next) + { + if (strcmp(opt->option, opt_name) == 0) + return opt; + } + + return NULL; +} + +void cmd_option_delete(struct CmdOption* opt) +{ + if (opt == NULL) + return; + + LIST_REMOVE(opt, next); + if (opt->option != NULL) + free(opt->option); + if (opt->parameter != NULL) + free(opt->parameter); + if (opt->desc != NULL) + free(opt->desc); + free(opt); +} + +struct CmdOption* cmd_option_add(struct CmdOptionParser* parser, char* opt_name) +{ + struct CmdOption* opt = NULL; + + if (opt_name == NULL) + return NULL; + if ((opt = cmd_option_find(parser, opt_name)) != NULL) + return opt; + + if ((opt = (struct CmdOption*) malloc(sizeof(struct CmdOption))) == NULL) + { + strerror(errno); + } + else + { + opt->option = opt_name; + opt->parameter = NULL; + opt->desc = NULL; + LIST_INSERT_HEAD(&(parser->option_list), opt, next); + } + + return opt; +} + +static void cmd_option_register(struct CmdOptionParser* parser, char* syntax, char* desc) +{ + char buf[OPTION_MAX_LEN]; + struct CmdOption* opt = NULL; + char* opt_name = NULL; + char* param = NULL; + char* desc_copy = NULL; + char* token = NULL; + + if (parser == NULL) + return; + if (syntax == NULL) + return; + + memset(buf, 0, OPTION_MAX_LEN); + snprintf(buf, OPTION_MAX_LEN - 1, "%s", syntax); + + if ((token = strtok(buf, " ")) == NULL) + return; + + opt_name = strdup(token); + if ((token = strtok(NULL, " ")) != NULL) + param = strdup(token); + desc_copy = strdup(desc); + if ((opt = cmd_option_find(parser, opt_name)) != NULL) + goto failed; + if ((opt = cmd_option_add(parser, opt_name)) == NULL) + { + goto failed; + } + opt->parameter = param; + opt->desc = desc_copy; + + return; + +failed: + if(opt_name) + free(opt_name); + if (desc_copy != NULL) + free(desc_copy); + if (param != NULL) + free(param); + if (opt != NULL) + free(opt); +} + +void cmd_option_parser_init(struct CmdOptionParser* parser) +{ + if (parser == NULL) + return; + + LIST_INIT(&parser->option_list); + cmd_option_register(parser, "-l ", "Set log file path.\n(Default: /var/log/iccpd.log)"); + cmd_option_register(parser, "-p ", "Set the port used for telnet listening port.\n(Default: 2015)"); + cmd_option_register(parser, "-c", "Dump log message to console. (Default: No)"); + cmd_option_register(parser, "-h", "Show the usage."); +} + +void cmd_option_parser_finalize(struct CmdOptionParser* parser) +{ + while (!LIST_EMPTY(&(parser->option_list))) + { + struct CmdOption* opt = NULL; + opt = LIST_FIRST(&(parser->option_list)); + cmd_option_delete(opt); + } +} + +void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_name) +{ + char buf[MSG_LEN]; + struct CmdOption* opt = NULL; + int index, begin, length; + char first_line = 0; + + fprintf(stdout, "Usage: %s [Options]\n", prog_name); + fprintf(stdout, "\n"); + fprintf(stdout, "Options:\n"); + LIST_FOREACH(opt, &(parser->option_list), next) + { + index = 0; + begin = 0; + length = 0; + first_line = 1; + memset(buf, 0, MSG_LEN); + if (opt->parameter != NULL) + snprintf(buf, MSG_LEN - 1, "%s %s", opt->option, opt->parameter); + else + snprintf(buf, MSG_LEN - 1, "%s", opt->option); + fprintf(stdout, "%24s ", buf); + while (index < strlen(opt->desc)) + { + while (index < strlen(opt->desc) + && opt->desc[index] != '\n' && length < 49) + { + ++index; + ++length; + } + memset(buf, 0, MSG_LEN); + strncpy(buf, &(opt->desc[begin]), length); + if (length == 49 && index < strlen(opt->desc) + && opt->desc[index] != '\n' + && opt->desc[index - 1] != ' ' + && opt->desc[index] != ' ') + { + buf[length] = '-'; + buf[length + 1] = '\0'; + } + if (length < 49) ++index; + begin = index; + length = 0; + if (first_line != 0) + { + fprintf(stdout, "%-52s\n", buf); + first_line = 0; + } + else + fprintf(stdout, "%28c%-52s\n", ' ', buf); + } + fflush(stdout); + } +} + +int cmd_option_parser_parse(struct CmdOptionParser* parser, int argc, char* argv[]) +{ + int index = 1; + struct CmdOption* opt = NULL; + char* opt_name = NULL; + char* val = NULL; + int num = 0; + + if (parser == NULL) + return -255; + + while (index < argc) + { + opt_name = argv[index]; + opt = cmd_option_find(parser, opt_name); + if (opt == NULL) + { + fprintf(stderr, "Unknown option %s, skip it.\n", opt_name); + ++index; + continue; + } + + if (opt->parameter != NULL) + { + ++index; + if (index >= argc) + { + fprintf(stderr, "Error: Insufficient parameter for option %s\n", opt_name); + cmd_option_parser_dump_usage(parser, argv[0]); + return -1; + } + val = argv[index]; + } + + if (strncmp(opt_name, "-h", 2) == 0) + { + cmd_option_parser_dump_usage(parser, argv[0]); + return -1; + } + + if (strncmp(opt_name, "-l", 2) == 0) + parser->log_file_path = val; + + if (strncmp(opt_name, "-p", 2) == 0) + { + num = atoi(val); + if (num > 0 && num < 65535) + parser->telnet_port = num; + } + else if (strncmp(opt_name, "-c", 2) == 0) + parser->console_log = 1; + else + fprintf(stderr, "Unknown option name %s, skip it.\n", opt_name); + + ++index; + } + + return 0; +} diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c new file mode 100644 index 000000000000..73eb16ddacd6 --- /dev/null +++ b/src/iccpd/src/iccp_cli.c @@ -0,0 +1,363 @@ +/* +* iccp_cli.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_link_handler.h" + +/* +* 'id <1-65535>' command +*/ +int set_mc_lag_id( struct CSM *csm, uint16_t id) +{ + if (!csm) return -1; + + ICCPD_LOG_INFO(__FUNCTION__, "Set mlag-id : %d", id); + + /* Mlag-ID, RG-ID, MLACP-ID + Temporary let the three id be the same*/ + csm->mlag_id = id; + csm->iccp_info.icc_rg_id = id; + csm->app_csm.mlacp.id = id; + return 0; +} + +int unset_mc_lag_id( struct CSM *csm, uint16_t id) +{ + if (!csm) return -1; + + /* Mlag-ID, RG-ID, MLACP-ID*/ + csm->mlag_id = 0; + csm->iccp_info.icc_rg_id = 0; + csm->app_csm.mlacp.id = 0; + + iccp_csm_finalize(csm); + + return 0; +} + +/* +* 'peer-link WORD' command +*/ +int set_peer_link(int mid, const char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface *lif = NULL; + size_t len = 0; + + len = strlen(ifname); + + if (strncmp(ifname, "Eth", 3) != 0 && strncmp(ifname, "Por", 3) != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Peer-link is %s, must be Ethernet or PortChannel", ifname); + return -1; + } + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + + if (len > IFNAMSIZ) return -1; + + if (strlen(csm->peer_itf_name) > 0) + { + if(strcmp(csm->peer_itf_name, ifname) == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer-link not be changed"); + return 0; + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Change peer-link : %s -> %s", + csm->peer_itf_name, ifname); + + scheduler_session_disconnect_handler(csm); + + if(csm->peer_link_if) + { + csm->peer_link_if->is_peer_link = 0; + csm->peer_link_if = NULL; + } + } + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Set mlag %d peer-link : %s", + csm->mlag_id,ifname); + } + + memset(csm->peer_itf_name, 0, IFNAMSIZ); + memcpy(csm->peer_itf_name, ifname, len); + + /* update peer-link link handler*/ + lif = local_if_find_by_name(csm->peer_itf_name); + if (lif) + { + csm->peer_link_if = lif; + lif->is_peer_link = 1; + MLACP(csm).system_config_changed = 1; + + if(lif->type == IF_T_PORT_CHANNEL) + iccp_get_port_member_list(lif); + } + + return 0; +} + +int unset_peer_link(int mid) +{ + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*must be enabled mac learn*/ + set_peerlink_mlag_port_learn(csm->peer_link_if, 1); + } + + /* Clean all port block*/ + peerlink_port_isolate_cleanup(csm); + + /* update peer-link link handler*/ + scheduler_session_disconnect_handler(csm); + + /* clean peer-link*/ + memset(csm->peer_itf_name, 0, IFNAMSIZ); + if(csm->peer_link_if) + { + csm->peer_link_if->is_peer_link = 0; + csm->peer_link_if = NULL; + MLACP(csm).system_config_changed = 1; + } + + return 0; +} + +/* +* 'local ip address A.B.C.D' command +*/ +int set_local_address(int mid, const char* addr) +{ + struct CSM* csm = NULL; + size_t len = 0; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + if (addr == NULL) return -1; + + if (strlen(csm->sender_ip) > 0) { + if (strcmp(csm->sender_ip, addr) == 0) { + ICCPD_LOG_INFO(__FUNCTION__, "Local-address not be changed"); + return 0; + } + else { + ICCPD_LOG_INFO(__FUNCTION__, "Change local-address : %s -> %s", + csm->sender_ip, addr); + scheduler_session_disconnect_handler(csm); + } + } + else { + ICCPD_LOG_INFO(__FUNCTION__, "Set local-address : %s", addr); + } + + len = strlen(addr); + memset(csm->sender_ip, 0, INET_ADDRSTRLEN); + memcpy(csm->sender_ip, addr, len); + memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); + memcpy(csm->iccp_info.sender_name, addr, len); + + return 0; +} + +int unset_local_address(int mid) +{ + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + + memset(csm->sender_ip, 0, INET_ADDRSTRLEN); + memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); + + /* reset link*/ + scheduler_session_disconnect_handler(csm); + + return 0; +} + +/* +* 'peer-address A.B.C.D' command +*/ +int set_peer_address(int mid, const char* addr) +{ + struct CSM* csm = NULL; + size_t len = 0; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + if(addr == NULL) return -1; + + len = strlen(addr); + + if (strlen(csm->peer_ip) > 0) + { + if(strcmp(csm->peer_ip, addr) == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer-address not be changed"); + return 0; + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Change peer-address : %s -> %s", + csm->peer_ip, addr); + scheduler_session_disconnect_handler(csm); + } + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Set peer-address : %s", addr); + } + + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); + memcpy(csm->peer_ip, addr, len); + + return 0; +} + +int unset_peer_address(int mid) +{ + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); + + /* reset link*/ + scheduler_session_disconnect_handler(csm); + + return 0; +} + +int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname) +{ + struct CSM* csm = NULL; + int i = 0; + int id = 0; + int len = 0; + struct LocalInterface *lif = NULL; + struct If_info * cif = NULL; + + if (!ifname) + return -1; + + if(strncmp(ifname, "Po", 2)!=0) { + ICCPD_LOG_DEBUG(__FUNCTION__, + "attach interface(%s) is not a port-channel", ifname); + return -1; + } + + csm = system_get_csm_by_mlacp_id(domain); + if (csm == NULL) { + ICCPD_LOG_DEBUG(__FUNCTION__, "MC-LAG ID %d doesn't exist", domain); + return -1; + } + + lif = local_if_find_by_name(ifname); + if (lif) + { + mlacp_bind_port_channel_to_csm(csm, ifname); + } + + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + if (strcmp(cif->name,ifname) ==0) + break; + } + + if(cif == NULL) + { + cif = (struct If_info *) malloc(sizeof(struct If_info)); + if (!cif) + return -1; + + snprintf(cif->name, MAX_L_PORT_NAME, "%s", ifname); + LIST_INSERT_HEAD(&(csm->if_bind_list), cif, csm_next); + } + + return 0; +} + +int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) +{ + int unbind_poid = -1; + struct CSM *csm = NULL; + struct LocalInterface *lif_po = NULL; + struct LocalInterface *lif = NULL; + struct If_info * cif = NULL; + + if (!ifname) + return -1; + + if (strncmp(ifname, "Po", 2)!=0) { + ICCPD_LOG_DEBUG(__FUNCTION__, + "detach interface(%s) is not a port-channel", ifname); + return -1; + } + + /* find po*/ + if (!(lif_po = local_if_find_by_name(ifname)) + || lif_po->type != IF_T_PORT_CHANNEL + || lif_po->po_id <=0 + || lif_po->csm == NULL) + { + return -1; + } + + /* find csm*/ + csm = lif_po->csm; + + ICCPD_LOG_DEBUG(__FUNCTION__, "detach mclag id = %d from ifname = %s", + csm->mlag_id, lif_po->name); + + /* process link state handler before detaching it.*/ + mlacp_mlag_link_del_handler(csm, lif_po); + + unbind_poid = lif_po->po_id; + mlacp_unbind_local_if(lif_po); + LIST_FOREACH(lif, &(csm->app_csm.mlacp.lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT && lif->po_id == unbind_poid) + mlacp_unbind_local_if(lif); + } + + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + if (strcmp(ifname, cif->name) ==0) + LIST_REMOVE(cif, csm_next); + } + return 0; +} diff --git a/src/iccpd/src/iccp_cmd.c b/src/iccpd/src/iccp_cmd.c new file mode 100644 index 000000000000..f5c17aad7d55 --- /dev/null +++ b/src/iccpd/src/iccp_cmd.c @@ -0,0 +1,160 @@ +/* +* iccp_cmd.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include + +#include "../include/iccp_csm.h" +#include "../include/msg_format.h" +#include "../include/system.h" + +#include "../include/iccp_cmd_show.h" +#include "../include/iccp_cli.h" +#include "../include/logger.h" + +int set_mc_lag_by_id(uint16_t mid) +{ + int ret = 0; + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if (!csm) + { + csm = (struct CSM*)iccp_get_csm(); + if (csm == NULL) + { + return -1; + } + + ret = set_mc_lag_id(csm, mid); + + return ret; + } + + return ret; +} + +#define CONFIG_LINE_LEN 512 + +int iccp_config_from_command(char * line) +{ + char *cp, *start; + char token[64]; + int slen; + static int mid = 0; + char *end; + + if (line == NULL) + return 0; + + cp = line; + + /* Skip white spaces. */ + while (isspace ((int) *cp) && *cp != '\0') + cp++; + + /* Return if there is only white spaces */ + if (*cp == '\0') + return 0; + + end = cp; + + /* Skip end white spaces. */ + while (!isspace ((int) *end) && *end != '\0') + end++; + + *end = '\0'; + /*mc-lag id*/ + if (strncmp(cp,"mclag_id:",9) == 0 ) + { + cp += 9; + mid = atoi(cp); + set_mc_lag_by_id(mid); + } + else if (strncmp(cp,"local_ip:",9) == 0) /*local ip*/ + { + cp += 9; + set_local_address(mid,cp); + } + else if (strncmp(cp,"peer_ip:",8) == 0) /*peer ip*/ + { + cp += 8; + set_peer_address(mid,cp); + } + else if(strncmp(cp,"peer_link:",10) == 0) + { + cp += 10; + set_peer_link(mid,cp); + } + else if(strncmp(cp,"bind_lacp:",10) == 0) + { + cp += 10; + + while (1) + { + start = cp; + while (!(*cp == ',' || *cp == '\r' || *cp == '\n') && + *cp != '\0') + cp++; + slen = cp - start; + strncpy (token, start, slen); + *(token + slen) = '\0'; + iccp_cli_attach_mclag_domain_to_port_channel(mid, token); + + while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r' || *cp == ',') && + *cp != '\0') + cp++; + + if (*cp == '\0') + break; + } + } + else + { + /*error*/ + } + + return 1; +} + +/* Configration make from file. */ +int +iccp_config_from_file (char *config_default_dir) +{ + FILE *confp = NULL; + char command_buf[CONFIG_LINE_LEN]; + + confp = fopen (config_default_dir, "r"); + if (confp == NULL) + return (1); + + while (fgets (command_buf, CONFIG_LINE_LEN, confp)) + { + iccp_config_from_command(command_buf); + } + fclose(confp); + + return 0; +} + diff --git a/src/iccpd/src/iccp_cmd_show.c b/src/iccpd/src/iccp_cmd_show.c new file mode 100644 index 000000000000..6fae86650f11 --- /dev/null +++ b/src/iccpd/src/iccp_cmd_show.c @@ -0,0 +1,474 @@ +/* +* iccp_cmd_show.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include + +#include "../include/iccp_csm.h" +#include "../include/mlacp_tlv.h" +#include "../include/system.h" +#include "../include/logger.h" +#include "mclagdctl/mclagdctl.h" +#include "../include/mlacp_link_handler.h" +#include "../include/iccp_cmd_show.h" + +int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) +{ + struct mclagd_state state_info; + struct System *sys = NULL; + struct CSM *csm = NULL; + struct LocalInterface *peer_link_if = NULL; + struct LocalInterface *lif_po = NULL; + char unknown[] = {"UNKNOWN"}; + int mclag_num= 0; + int id_exist = 0; + char * str_buf =NULL; + int str_size =0; + int len = 0; + char *state_buf = NULL; + int state_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + state_buf = (char*)malloc(state_buf_size); + if (!state_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + memset(&state_info, 0, sizeof(struct mclagd_state)); + + if (csm->current_state == ICCP_OPERATIONAL) + state_info.keepalive = 1; + else + state_info.keepalive = 0; + + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + peer_link_if = local_if_find_by_name(csm->peer_itf_name); + + if (csm->mlag_id <= 0) + state_info.mclag_id = -1; + else + state_info.mclag_id = csm->mlag_id; + + memcpy(state_info.local_ip, csm->sender_ip, ICCP_MAX_IP_STR_LEN); + memcpy(state_info.peer_ip, csm->peer_ip, ICCP_MAX_IP_STR_LEN); + + if (peer_link_if) + memcpy(state_info.peer_link_if, peer_link_if->name, ICCP_MAX_PORT_NAME); + else + memcpy(state_info.peer_link_if, unknown, strlen(unknown)); + + if (peer_link_if) + memcpy(state_info.peer_link_mac, peer_link_if->mac_addr, 6); + + state_info.role = csm->role_type; + + str_buf = state_info.enabled_po; + str_size = MCLAGDCTL_PORT_MEMBER_BUF_LEN; + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + + if (str_size -len < ICCP_MAX_PORT_NAME) + break; + + if (lif_po->type == IF_T_PORT_CHANNEL) + len += snprintf(str_buf + len, str_size - len, "%s,", lif_po->name); + } + + memcpy(state_buf + MCLAGD_REPLY_INFO_HDR + mclag_num*sizeof(struct mclagd_state), + &state_info, sizeof(struct mclagd_state)); + + mclag_num ++; + + if ((mclag_num + 1)*sizeof(struct mclagd_state) > (state_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + state_buf_size += MCLAGDCTL_CMD_SIZE; + state_buf = (char*)realloc(state_buf, state_buf_size); + if (!state_buf) + return EXEC_TYPE_FAILED; + } + } + + *buf = state_buf; + *num = mclag_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_arp_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct ARPMsg *iccpd_arp = NULL; + struct mclagd_arp_msg mclagd_arp; + int arp_num = 0; + int id_exist = 0; + char * arp_buf = NULL; + int arp_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + arp_buf = (char*)malloc(arp_buf_size); + if (!arp_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + memset(&mclagd_arp, 0, sizeof(struct mclagd_arp_msg)); + iccpd_arp = (struct ARPMsg*)msg->buf; + + mclagd_arp.op_type = iccpd_arp->op_type; + memcpy(mclagd_arp.ifname, iccpd_arp->ifname, strlen(iccpd_arp->ifname)); + memcpy(mclagd_arp.ipv4_addr, show_ip_str(iccpd_arp->ipv4_addr), 16); + memcpy(mclagd_arp.mac_addr, iccpd_arp->mac_addr, 6); + + memcpy(arp_buf + MCLAGD_REPLY_INFO_HDR +arp_num*sizeof(struct mclagd_arp_msg), + &mclagd_arp, sizeof(struct mclagd_arp_msg)); + + arp_num ++; + + if ((arp_num + 1)*sizeof(struct mclagd_arp_msg) > (arp_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + arp_buf_size += MCLAGDCTL_CMD_SIZE; + arp_buf = (char*)realloc(arp_buf, arp_buf_size); + if (!arp_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = arp_buf; + *num = arp_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_mac_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct MACMsg *iccpd_mac = NULL; + struct mclagd_mac_msg mclagd_mac; + int mac_num = 0; + int id_exist = 0; + char * mac_buf = NULL; + int mac_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + mac_buf = (char*)malloc(mac_buf_size); + if (!mac_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + memset(&mclagd_mac, 0, sizeof(struct mclagd_mac_msg)); + iccpd_mac = (struct MACMsg*)msg->buf; + + mclagd_mac.op_type = iccpd_mac->op_type; + mclagd_mac.fdb_type = iccpd_mac->fdb_type; + memcpy(mclagd_mac.mac_str, iccpd_mac->mac_str, 32); + mclagd_mac.vid = iccpd_mac->vid; + memcpy(mclagd_mac.ifname, iccpd_mac->ifname, strlen(iccpd_mac->ifname)); + memcpy(mclagd_mac.origin_ifname, iccpd_mac->origin_ifname, strlen(iccpd_mac->origin_ifname)); + mclagd_mac.age_flag = iccpd_mac->age_flag; + + memcpy(mac_buf + MCLAGD_REPLY_INFO_HDR + mac_num*sizeof(struct mclagd_mac_msg), + &mclagd_mac, sizeof(struct mclagd_mac_msg)); + + mac_num ++; + + if ((mac_num + 1)*sizeof(struct mclagd_mac_msg) > (mac_buf_size -MCLAGD_REPLY_INFO_HDR)) + { + mac_buf_size += MCLAGDCTL_CMD_SIZE; + mac_buf = (char*)realloc(mac_buf, mac_buf_size); + if (!mac_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = mac_buf; + *num = mac_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_local_if_dump(char * *buf, int *num,int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct LocalInterface *lif_po = NULL; + struct mclagd_local_if mclagd_lif; + struct VLAN_ID* vlan_id = NULL; + char * str_buf = NULL; + int str_size = MCLAGDCTL_PARA3_LEN - 1; + int len = 0; + int lif_num = 0; + int id_exist = 0; + int lif_buf_size = MCLAGDCTL_CMD_SIZE; + char * lif_buf = NULL; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + lif_buf = (char*)malloc(lif_buf_size); + if (!lif_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + memset(&mclagd_lif, 0, sizeof(struct mclagd_local_if)); + + mclagd_lif.ifindex = lif_po->ifindex; + + if (lif_po->type == IF_T_UNKNOW) + memcpy(mclagd_lif.type, "UNKNOW", 6); + else if (lif_po->type == IF_T_PORT) + memcpy(mclagd_lif.type, "PORT", 4); + else if (lif_po->type == IF_T_PORT_CHANNEL) + memcpy(mclagd_lif.type, "PORT-CHANNEL", 12); + + memcpy(mclagd_lif.name, lif_po->name, MAX_L_PORT_NAME); + memcpy(mclagd_lif.mac_addr, lif_po->mac_addr, ETHER_ADDR_LEN); + + if (lif_po->state == PORT_STATE_UP) + memcpy(mclagd_lif.state, "UP", 2); + else if (lif_po->state == PORT_STATE_DOWN) + memcpy(mclagd_lif.state, "DOWN", 4); + else if (lif_po->state == PORT_STATE_ADMIN_DOWN) + memcpy(mclagd_lif.state, "ADMIN-DOWN", 10); + else if (lif_po->state == PORT_STATE_TEST) + memcpy(mclagd_lif.state, "TEST", 4); + + memcpy(mclagd_lif.ipv4_addr, show_ip_str(htonl(lif_po->ipv4_addr)), 16); + mclagd_lif.prefixlen = lif_po->prefixlen; + + mclagd_lif.l3_mode = local_if_is_l3_mode(lif_po); + + mclagd_lif.is_peer_link = lif_po->is_peer_link; + + memcpy(mclagd_lif.portchannel_member_buf, lif_po->portchannel_member_buf, 512); + + mclagd_lif.po_id = lif_po->po_id; + mclagd_lif.po_active = lif_po->po_active; + /*mlacp_state*/ + if (lif_po->mlacp_state == MLACP_STATE_INIT) + memcpy(mclagd_lif.mlacp_state, "INIT", 4); + else if (lif_po->mlacp_state == MLACP_STATE_STAGE1) + memcpy(mclagd_lif.mlacp_state, "STAGE1", 6); + else if (lif_po->mlacp_state == MLACP_STATE_STAGE2) + memcpy(mclagd_lif.mlacp_state, "STAGE2", 6); + else if (lif_po->mlacp_state == MLACP_STATE_EXCHANGE) + memcpy(mclagd_lif.mlacp_state, "EXCHANGE", 8); + else if (lif_po->mlacp_state == MLACP_STATE_ERROR) + memcpy(mclagd_lif.mlacp_state, "ERROR", 5); + + mclagd_lif.isolate_to_peer_link = lif_po->isolate_to_peer_link; + + str_buf = mclagd_lif.vlanlist; + + len = 0; + LIST_FOREACH(vlan_id, &(lif_po->vlan_list), port_next) + { + if (vlan_id != NULL ) + { + if (str_size -len < 4) + break; + len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid); + } + } + + memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num*sizeof(struct mclagd_local_if), + &mclagd_lif, sizeof(struct mclagd_local_if)); + + lif_num ++; + + if ((lif_num + 1)*sizeof(struct mclagd_local_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + lif_buf_size += MCLAGDCTL_CMD_SIZE; + lif_buf = (char*)realloc(lif_buf, lif_buf_size); + if (!lif_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = lif_buf; + *num = lif_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct PeerInterface *pif_po = NULL; + struct mclagd_peer_if mclagd_pif; + int pif_num = 0; + int id_exist = 0; + int pif_buf_size = MCLAGDCTL_CMD_SIZE; + char *pif_buf = NULL; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + pif_buf = (char*)malloc(pif_buf_size); + if (!pif_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + LIST_FOREACH(pif_po, &(MLACP(csm).pif_list), mlacp_next) + { + memset(&mclagd_pif, 0, sizeof(struct mclagd_peer_if)); + + mclagd_pif.ifindex = pif_po->ifindex; + + if (pif_po->type == IF_T_UNKNOW) + memcpy(mclagd_pif.type, "UNKNOW", 6); + else if (pif_po->type == IF_T_PORT) + memcpy(mclagd_pif.type, "PORT", 4); + else if (pif_po->type == IF_T_PORT_CHANNEL) + memcpy(mclagd_pif.type, "PORT-CHANNEL", 12); + + memcpy(mclagd_pif.name, pif_po->name, MAX_L_PORT_NAME); + memcpy(mclagd_pif.mac_addr, pif_po->mac_addr, ETHER_ADDR_LEN); + + if (pif_po->state == PORT_STATE_UP) + memcpy(mclagd_pif.state, "UP", 2); + else if (pif_po->state == PORT_STATE_DOWN) + memcpy(mclagd_pif.state, "DOWN", 4); + else if (pif_po->state == PORT_STATE_ADMIN_DOWN) + memcpy(mclagd_pif.state, "ADMIN-DOWN", 10); + else if (pif_po->state == PORT_STATE_TEST) + memcpy(mclagd_pif.state, "TEST", 4); + + mclagd_pif.po_id = pif_po->po_id; + mclagd_pif.po_active = pif_po->po_active; + + memcpy(pif_buf + MCLAGD_REPLY_INFO_HDR + pif_num*sizeof(struct mclagd_peer_if), + &mclagd_pif, sizeof(struct mclagd_peer_if)); + + pif_num ++; + + if ((pif_num + 1)*sizeof(struct mclagd_peer_if) > (pif_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + pif_buf_size += MCLAGDCTL_CMD_SIZE; + pif_buf = (char*)realloc(pif_buf, pif_buf_size); + if (!pif_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = pif_buf; + *num = pif_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + diff --git a/src/iccpd/src/iccp_consistency_check.c b/src/iccpd/src/iccp_consistency_check.c new file mode 100644 index 000000000000..da5076b4b10d --- /dev/null +++ b/src/iccpd/src/iccp_consistency_check.c @@ -0,0 +1,175 @@ +/* +* iccp_consistency_check.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +* +*/ + +#include "../include/iccp_consistency_check.h" +#include "../include/system.h" +#include "../include/port.h" +#include "../include/logger.h" + +/* Return 0 if the checking procedure is failed; otherwise, 1 (non-zero) will be returned. */ +typedef int (*ConsistencyCheckFunc)(char* ifname); + +const char *reasons[] = { + /* REASON_NONE */ + "Success", + /* REASON_INTERRFACE_MODE_IS_ASYNC */ + "Port-channel interface is not in the same mode in local and peer device, please check whether the ip addr settings is correct or not.", + /* REASON_PEER_IF_IP_IS_ASYNC */ + "IP address of peer interface is not synchronized, please check the IP address setting on the corresponding interface.", + /* REASON_PEER_IF_VLAN_IS_ASYNC */ + "VLAN settings on this port-channel interface is not synchronized, please check your configuration.", + /* REASON_MAX_ARRAY_SIZE */ + NULL +}; + +/* Consistency Checking functions */ +static int iccp_check_interface_mode( char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + struct PeerInterface* peer_if = NULL; + + local_if = local_if_find_by_name(ifname); + if(local_if == NULL) + return -2; + + csm = local_if->csm; + if(csm == NULL) + return -3; + + peer_if = peer_if_find_by_name(csm, ifname); + if(peer_if == NULL) + return -4; + + if(peer_if->l3_mode != local_if->l3_mode) + return -5; + + return 1; +} + +static int iccp_check_interface_layer3_addr(char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + struct PeerInterface* peer_if = NULL; + + local_if = local_if_find_by_name(ifname); + if(local_if == NULL) + return -2; + + csm = local_if->csm; + if(csm == NULL) + return -3; + + peer_if = peer_if_find_by_name(csm, ifname); + if(peer_if == NULL) + return -4; + + if(peer_if->ipv4_addr != local_if->ipv4_addr) + return -5; + + return 1; +} + +static int iccp_check_interface_vlan(char* ifname) +{ + struct CSM* csm = NULL; + struct PeerInterface* peer_if = NULL; + struct VLAN_ID* local_vlan = NULL; + struct VLAN_ID* peer_vlan = NULL; + struct LocalInterface* local_if = NULL; + + local_if = local_if_find_by_name(ifname); + if(local_if == NULL) + return -2; + + csm = local_if->csm; + if(csm == NULL) + return -3; + + peer_if = peer_if_find_by_name(csm, ifname); + if(peer_if == NULL) + return -4; + + LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next) + { + LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) + { + if(peer_vlan->vid == local_vlan->vid) + break; + } + + if(peer_vlan == NULL) + { + return -5; + } + } + + LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) + { + + LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next) + { + if(peer_vlan->vid == local_vlan->vid) + break; + } + + if(local_vlan == NULL) + { + return -6; + } + } + + return 1; +} + +static const ConsistencyCheckFunc check_func[] = { + NULL, + iccp_check_interface_mode, /* REASON_INTERFACE_MODE_IS_ASYNC */ + iccp_check_interface_layer3_addr, /* REASON_PEER_IF_IP_IS_ASYNC */ + iccp_check_interface_vlan, /* REASON_PEER_IF_VLAN_IS_ASYNC */ + NULL /* REASON_MAX_ARRAY_SIZE */ +}; +#define ARRAY_SIZE(array_name) (sizeof(array_name)/sizeof(array_name[0])) + +enum Reason_ID iccp_consistency_check(char* ifname) +{ + int i = 0; + int ret = 0; + + for(i = REASON_INTERRFACE_MODE_IS_ASYNC; i < REASON_MAX_ARRAY_SIZE; ++i) + { + if(check_func[i] == NULL) + continue; + ret = check_func[i](ifname) ; + if(ret != 1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s ret = %d",reasons[i] ,ret); + fprintf(stdout,"%s \n",reasons[i]); + return i; + } + } + + return REASON_NONE; +} diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c new file mode 100644 index 000000000000..601a03c34553 --- /dev/null +++ b/src/iccpd/src/iccp_csm.c @@ -0,0 +1,746 @@ +/* +* iccp_csm.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include + +#include "../include/logger.h" +#include "../include/system.h" +#include "../include/msg_format.h" +#include "../include/mlacp_link_handler.h" + +/***************************************** +* Define +* +* ***************************************/ +#define ICCP_CSM_QUEUE_REINIT(list) \ + {\ + struct Msg* msg = NULL;\ + while (!TAILQ_EMPTY(&(list))) {\ + msg = TAILQ_FIRST(&(list));\ + TAILQ_REMOVE(&(list), msg, tail);\ + free(msg->buf);\ + free(msg);\ + }\ + TAILQ_INIT(&(list));\ + } + +/***************************************** +* Global +* +* ***************************************/ +char g_csm_buf[CSM_BUFFER_SIZE]={0}; + +uint32_t ICCP_MSG_ID = 0x1; + +/* Enter Connection State Machine NONEXISTENT handle function */ +static void iccp_csm_enter_state_nonexistent(struct CSM* csm) +{ + iccp_csm_finalize(csm); +} + +/* Enter Connection State Machine INITIALIZED handle function */ +static void iccp_csm_enter_state_initialized(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_capability_flag = 0x1; +} + +/* Enter Connection State Machine CAPREC handle function */ +static void iccp_csm_enter_state_caprec(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_capability_flag = 0x1; + csm->iccp_info.peer_capability_flag = 0x1; +} + +/* Enter Connection State Machine CONNECTING handle function */ +static void iccp_csm_enter_state_connecting(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_rg_connect_flag = 0x1; +} + +/* Enter Connection State Machine OPERATIONAL handle function */ +static void iccp_csm_enter_state_operational(struct CSM* csm) { + if (csm == NULL) + return; + + csm->iccp_info.sender_rg_connect_flag = 0x1; + csm->iccp_info.peer_rg_connect_flag = 0x1; +} + +void *iccp_get_csm() +{ + struct CSM* csm = NULL; + struct System* sys = NULL; + + if((sys = system_get_instance()) == NULL) { + return NULL; + } + + csm = system_create_csm(); + + return csm; +} + +/* Connection State Machine instance initialization */ +void iccp_csm_init(struct CSM* csm) +{ + iccp_csm_status_reset(csm, 1); + memset(csm->sender_ip, 0, INET_ADDRSTRLEN); + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); + memset(csm->iccp_info.sender_name, 0, MAX_L_ICC_SENDER_NAME); + csm->iccp_info.icc_rg_id = 0x0; +} + +/* Connection State Machine instance status reset */ +void iccp_csm_status_reset(struct CSM* csm, int all) +{ + ICCP_CSM_QUEUE_REINIT(csm->msg_list); + + if(all) + { + bzero(csm, sizeof(struct CSM)); + ICCP_CSM_QUEUE_REINIT(csm->msg_list); + } + + csm->sock_fd = -1; + pthread_mutex_init(&csm->conn_mutex, NULL); + csm->connTimePrev = 0; + csm->heartbeat_send_time = 0; + csm->heartbeat_update_time = 0; + csm->sysid_update_time = 0; + csm->isolate_update_time = 0; + csm->role_type = STP_ROLE_NONE; + csm->sock_read_event_ptr = NULL; + csm->peer_link_if = NULL; + csm->u_msg_in_count= 0x0; + csm->i_msg_in_count = 0x0; + csm->icc_msg_in_count = 0x0; + csm->icc_msg_out_count = 0x0; + csm->iccp_info.status_code = 0x0; + csm->iccp_info.rejected_msg_id = 0x0; + csm->current_state = ICCP_NONEXISTENT; + csm->iccp_info.peer_capability_flag = 0x0; + csm->iccp_info.peer_rg_connect_flag = 0x0; + csm->iccp_info.sender_capability_flag = 0x0; + csm->iccp_info.sender_rg_connect_flag = 0x0; + app_csm_init(csm, all); + + memset(&csm->msg_log, 0, sizeof(struct MsgLog)); +} + +/* Connection State Machine instance tear down */ +void iccp_csm_finalize(struct CSM* csm) +{ + struct If_info * cif = NULL; + if (csm == NULL) + return; + + /* Clean all port block*/ + peerlink_port_isolate_cleanup(csm); + + /* Disconnect from peer */ + scheduler_session_disconnect_handler(csm); + + /* Release all Connection State Machine instance */ + app_csm_finalize(csm); + + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + LIST_REMOVE(cif, csm_next); + } + + /* Release iccp_csm */ + pthread_mutex_destroy(&(csm->conn_mutex)); + iccp_csm_msg_list_finalize(csm); + LIST_REMOVE(csm, next); + free(csm); +} + +/* Message list of Connection State Machine instance tear down */ +void iccp_csm_msg_list_finalize(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (csm == NULL) + return; + + while (!TAILQ_EMPTY(&(csm->msg_list))) + { + msg = TAILQ_FIRST(&(csm->msg_list)); + TAILQ_REMOVE(&(csm->msg_list), msg, tail); + free(msg); + } +} + +/* Send message to peer */ +int iccp_csm_send(struct CSM* csm, char* buf, int msg_len) +{ + LDPHdr* ldp_hdr = (LDPHdr*) buf; + ICCParameter* param = NULL; + + if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0) + return -1; + + if(ldp_hdr->msg_type == MSG_T_CAPABILITY) + param = (struct ICCParameter*)&buf[sizeof(LDPHdr)]; + else + param = (struct ICCParameter*)&buf[sizeof(ICCHdr)]; + + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Send(%d): len=[%d] msg_type=[%s (0x%X, 0x%X)]", csm->sock_fd, msg_len, get_tlv_type_string(param->type), ldp_hdr->msg_type, param->type);*/ + csm->msg_log.msg[csm->msg_log.end_index].msg_id = ldp_hdr->msg_id; + csm->msg_log.msg[csm->msg_log.end_index].type = ldp_hdr->msg_type; + csm->msg_log.msg[csm->msg_log.end_index].tlv = param->type; + ++csm->msg_log.end_index; + if(csm->msg_log.end_index >= 128) + csm->msg_log.end_index = 0; + + return write(csm->sock_fd, buf, msg_len); +} + +/* Connection State Machine Transition */ +void iccp_csm_transit(struct CSM* csm) +{ + int len = -1; + struct Msg* msg = NULL; + ICCP_CONNECTION_STATE_E prev_state; + + if (!csm) + return; + + prev_state = csm->current_state; + + /* No connection, but have state change? reset it...*/ + if (csm->current_state != ICCP_NONEXISTENT && csm->sock_fd <= 0) + { + csm->current_state = ICCP_NONEXISTENT; + iccp_csm_enter_state_nonexistent(csm); + return; + } + + /*if (csm->current_state != ICCP_NONEXISTENT) + ICCPD_LOG_DEBUG(__FUNCTION__, "#Begin# id:%d, fd:%d, ICCP CSM State:%d", csm->mlag_id, csm->sock_fd, csm->current_state);*/ + + msg = iccp_csm_dequeue_msg(csm); + + switch (csm->current_state) + { + case ICCP_NONEXISTENT: + scheduler_prepare_session(csm); + if (csm->sock_fd > 0 && scheduler_check_csm_config(csm) > 0) + csm->current_state = ICCP_INITIALIZED; + break; + case ICCP_INITIALIZED: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x0) + csm->current_state = ICCP_CAPSENT; + else if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x1) + csm->current_state = ICCP_CAPREC; + break; + case ICCP_CAPSENT: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x1) + csm->current_state = ICCP_CAPREC; + break; + case ICCP_CAPREC: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + if (csm->iccp_info.peer_rg_connect_flag == 0x0 && csm->iccp_info.status_code == 0x0) + csm->current_state = ICCP_CONNECTING; + else if (csm->iccp_info.peer_rg_connect_flag == 0x1 && csm->iccp_info.status_code == 0x0) + csm->current_state = ICCP_OPERATIONAL; + break; + case ICCP_CONNECTING: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + if (csm->iccp_info.status_code > 0x0) + csm->current_state = ICCP_CAPREC; + else if (csm->iccp_info.peer_rg_connect_flag == 0x1 && csm->iccp_info.status_code == 0x0) + csm->current_state = ICCP_OPERATIONAL; + break; + case ICCP_OPERATIONAL: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + if (csm->iccp_info.sender_rg_connect_flag == 0x0 || csm->iccp_info.peer_rg_connect_flag == 0x0) { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + csm->current_state = ICCP_CAPREC; + } + break; + default: + break; + } + + if (prev_state != csm->current_state || (csm->current_state && msg != NULL)) + { + ICCPD_LOG_INFO(__FUNCTION__, "csm %d enter state %d .", csm->mlag_id, csm->current_state); + + switch (csm->current_state) + { + case ICCP_NONEXISTENT: + iccp_csm_enter_state_nonexistent(csm); + break; + case ICCP_INITIALIZED: + iccp_csm_enter_state_initialized(csm); + break; + case ICCP_CAPSENT: + /* Do nothing on this state */ + break; + case ICCP_CAPREC: + iccp_csm_enter_state_caprec(csm); + break; + case ICCP_CONNECTING: + iccp_csm_enter_state_connecting(csm); + break; + case ICCP_OPERATIONAL: + iccp_csm_enter_state_operational(csm); + break; + default: + break; + } + } + /*if (csm->current_state != ICCP_NONEXISTENT && prev_state != csm->current_state) + ICCPD_LOG_DEBUG(__FUNCTION__, "#End# id:%d, fd:%d, ICCP CSM State:%d", csm->mlag_id, csm->sock_fd, csm->current_state);*/ +} + +/* Set up ICCP message */ +int iccp_csm_prepare_iccp_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + size_t msg_len = -1; + + if (csm == NULL || buf == NULL) + return -1; + + switch (csm->current_state) + { + case ICCP_NONEXISTENT: + /* Do nothing on this state */ + break; + case ICCP_INITIALIZED: + msg_len = iccp_csm_prepare_capability_msg(csm, buf, max_buf_size); + break; + case ICCP_CAPSENT: + /* Do nothing on this state */ + break; + case ICCP_CAPREC: + if (csm->iccp_info.status_code > 0x0) { + msg_len = iccp_csm_prepare_nak_msg(csm, buf, max_buf_size); + break; + } + msg_len = iccp_csm_prepare_rg_connect_msg(csm, buf, max_buf_size); + break; + case ICCP_CONNECTING: + if (csm->iccp_info.status_code > 0x0) { + msg_len = iccp_csm_prepare_nak_msg(csm, buf, max_buf_size); + break; + } + break; + case ICCP_OPERATIONAL: + if (csm->iccp_info.peer_rg_connect_flag == 0x0) { + msg_len = iccp_csm_prepare_rg_disconnect_msg(csm, buf, max_buf_size); + break; + } + break; + } + + return msg_len; +} + +/* ICCP capability message handle function */ +int iccp_csm_prepare_capability_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + LDPHdr* ldp_hdr = (LDPHdr*) buf; + LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*) &buf[sizeof(LDPHdr)]; + size_t msg_len = sizeof(LDPHdr) + sizeof(LDPICCPCapabilityTLV); + + memset(buf, 0, max_buf_size); + + /* LDP header */ + ldp_hdr->u_bit = 0x0; + ldp_hdr->msg_type = MSG_T_CAPABILITY; + ldp_hdr->msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + ldp_hdr->msg_id = ICCP_MSG_ID++; + + /* LDP ICCP capability TLV */ + cap->icc_parameter.u_bit = 0x1; + cap->icc_parameter.f_bit = 0x0; + cap->icc_parameter.type = TLV_T_ICCP_CAPABILITY; + cap->icc_parameter.len = TLV_L_ICCP_CAPABILITY; + cap->s_bit = csm->iccp_info.sender_capability_flag; + cap->major_ver = 0x1; + cap->minior_ver = 0x0; + + return msg_len; +} + +void iccp_csm_fill_icc_rg_id_tlv(struct CSM* csm, ICCHdr* icc_hdr) +{ + if (!csm || !icc_hdr) + return; + + icc_hdr->icc_rg_id_tlv.type = TLV_T_ICC_RG_ID; + icc_hdr->icc_rg_id_tlv.len = TLV_L_ICC_RG_ID; + icc_hdr->icc_rg_id_tlv.icc_rg_id = csm->iccp_info.icc_rg_id; +} + +/* ICCP NAK message handle function */ +int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + NAKTLV* nak = (NAKTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); + + memset(buf, 0, max_buf_size); + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_NOTIFICATION; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + /* NAL TLV */ + nak->icc_parameter.u_bit = 0x0; + nak->icc_parameter.f_bit = 0x0; + nak->icc_parameter.type = TLV_T_NAK; + nak->icc_parameter.len = sizeof(((struct NAKTLV*) 0)->iccp_status_code) + sizeof(((struct NAKTLV*) 0)->rejected_msg_id); + + switch (csm->iccp_info.status_code) + { + case STATUS_CODE_U_ICCP_RG: + nak->iccp_status_code = csm->iccp_info.status_code; + nak->rejected_msg_id = csm->iccp_info.rejected_msg_id; + break; + /* Unsupported */ + case STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED: + case STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED: + case STATUS_CODE_ICCP_APP_NOT_IN_RG: + case STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER: + case STATUS_CODE_ICCP_REJECTED_MSG: + case STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED: + case STATUS_CODE_ICCP_RG_REMOVED: + case STATUS_CODE_ICCP_APP_REMOVED_FROM_RG: + break; + } + + return msg_len; +} + +/* ICCP RG connect handle function */ +int iccp_csm_prepare_rg_connect_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + ICCSenderNameTLV* sender = (ICCSenderNameTLV*) &buf[sizeof(ICCHdr)]; + size_t name_len = strlen(csm->iccp_info.sender_name); + size_t msg_len = sizeof(ICCHdr) + sizeof(ICCParameter) + name_len; + + memset(buf, 0, max_buf_size); + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_RG_CONNECT; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + /* ICC sender name TLV */ + sender->icc_parameter.u_bit = 0x0; + sender->icc_parameter.f_bit = 0x0; + sender->icc_parameter.type = TLV_T_ICC_SENDER_NAME; + sender->icc_parameter.len = name_len; + memcpy(sender->sender_name, csm->iccp_info.sender_name, name_len); + + return msg_len; +} + +/* ICCP RG disconnect handle function */ +int iccp_csm_prepare_rg_disconnect_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + DisconnectCodeTLV* disconn_code = (DisconnectCodeTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(DisconnectCodeTLV); + + memset(buf, 0, max_buf_size); + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_RG_DISCONNECT; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + /* Disconnect code TLV */ + disconn_code->icc_parameter.u_bit = 0x0; + disconn_code->icc_parameter.f_bit = 0x0; + disconn_code->icc_parameter.type = TLV_T_DISCONNECT_CODE; + disconn_code->icc_parameter.len = sizeof(((struct DisconnectCodeTLV*) 0)->iccp_status_code); + disconn_code->iccp_status_code = csm->iccp_info.status_code; + + return msg_len; +} + +/* Check ID(MC-LAG ID, mLACP ID, RG ID) from received message */ +static void iccp_csm_check_id_from_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + + if (!csm || !msg || !msg->buf) + return; + + icc_hdr = (ICCHdr*) msg->buf; + + /* Capability Message doesn't have ICC RG ID TLV */ + if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) + return; + + /* Check if received message ID same as local configuration */ + if (icc_hdr->icc_rg_id_tlv.icc_rg_id == csm->iccp_info.icc_rg_id) + { + if (csm->iccp_info.status_code == STATUS_CODE_U_ICCP_RG) + { + csm->iccp_info.status_code = 0x0; + csm->iccp_info.rejected_msg_id = 0x0; + } + } else if (icc_hdr->icc_rg_id_tlv.icc_rg_id != csm->iccp_info.icc_rg_id) + { + csm->iccp_info.status_code = STATUS_CODE_U_ICCP_RG; + csm->iccp_info.rejected_msg_id = icc_hdr->icc_rg_id_tlv.icc_rg_id; + } +} + +/* Receive message correspond function */ +void iccp_csm_correspond_from_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + + if (csm == NULL || msg == NULL || msg->buf == NULL) + return; + + icc_hdr = (ICCHdr*) msg->buf; + NAKTLV* nak = (NAKTLV*)( icc_hdr+sizeof(ICCHdr)); + iccp_csm_check_id_from_msg(csm, msg); + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) + iccp_csm_correspond_from_capability_msg(csm, msg); + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_CONNECT) + iccp_csm_correspond_from_rg_connect_msg(csm, msg); + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_DISCONNECT) + iccp_csm_correspond_from_rg_disconnect_msg(csm, msg); + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Received MSG_T_NOTIFICATION ,err status %s reason of %s", get_status_string(nak->iccp_status_code), get_status_string(csm->iccp_info.status_code)); + sleep(1); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + ;// do nothing + } + else + { + ++csm->u_msg_in_count; + } + + free(msg->buf); + free(msg); +} + +/* Receive capability message correspond function */ +void iccp_csm_correspond_from_capability_msg(struct CSM* csm, struct Msg* msg) +{ + LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*) &(msg->buf)[sizeof(LDPHdr)]; + + if (cap->icc_parameter.u_bit == 0x1 + && cap->icc_parameter.f_bit == 0x0 + && cap->icc_parameter.type == TLV_T_ICCP_CAPABILITY + && cap->icc_parameter.len == (TLV_L_ICCP_CAPABILITY) + && cap->s_bit == 1 + && cap->major_ver == 0x1 + && cap->minior_ver == 0x0) + { + csm->iccp_info.peer_capability_flag = 0x1; + } +} + +/* Receive RG connect message correspond function */ +void iccp_csm_correspond_from_rg_connect_msg(struct CSM* csm, struct Msg* msg) +{ + ICCSenderNameTLV* sender = (ICCSenderNameTLV*) &(msg->buf)[sizeof(ICCHdr)]; + + if (sender->icc_parameter.u_bit == 0x0 && + sender->icc_parameter.f_bit == 0x0 && + sender->icc_parameter.type == TLV_T_ICC_SENDER_NAME) + { + csm->iccp_info.peer_rg_connect_flag = 0x1; + } +} + +/* Receive RG disconnect message correspond function */ +void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM* csm, struct Msg* msg) +{ + DisconnectCodeTLV* diconn_code = (DisconnectCodeTLV*) &(msg->buf)[sizeof(ICCHdr)]; + + if (diconn_code->icc_parameter.u_bit == 0x0 + && diconn_code->icc_parameter.f_bit == 0x0 + && diconn_code->icc_parameter.type == TLV_T_DISCONNECT_CODE + && diconn_code->icc_parameter.len == (TLV_L_DISCONNECT_CODE) + && diconn_code->iccp_status_code == (STATUS_CODE_ICCP_RG_REMOVED)) + { + csm->iccp_info.sender_rg_connect_flag = 0x0; + csm->iccp_info.peer_rg_connect_flag = 0x0; + } +} + +/* Add received message into message list */ +void iccp_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + NAKTLV* naktlv = NULL; + int type = -1; + int i = 0; + + if (csm == NULL) { + if (msg != NULL) + free(msg); + return; + } + + if (msg == NULL) + return; + + icc_hdr = (ICCHdr*) msg->buf; + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + app_csm_enqueue_msg(csm, msg); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + { + naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; + + for(i=0; irejected_msg_id == csm->msg_log.msg[i].msg_id) + { + type = csm->msg_log.msg[i].type; + break; + } + } + + if(type == MSG_T_RG_APP_DATA) + app_csm_enqueue_msg(csm, msg); + else + TAILQ_INSERT_TAIL(&(csm->msg_list), msg, tail); + } + else + { + TAILQ_INSERT_TAIL(&(csm->msg_list), msg, tail); + } +} + +/* Get received message from message list */ +struct Msg* iccp_csm_dequeue_msg(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (!TAILQ_EMPTY(&(csm->msg_list))) + { + msg = TAILQ_FIRST(&(csm->msg_list)); + TAILQ_REMOVE(&(csm->msg_list), msg, tail); + + } + + return msg; +} + +/* Message initialization */ +int iccp_csm_init_msg(struct Msg** msg, char* data, int len) +{ + struct Msg* iccp_msg = NULL; + + if (msg == NULL) + return -2; + + if(data == NULL || len <= 0) + return -1; + + iccp_msg = (struct Msg*) malloc(sizeof(struct Msg)); + if (iccp_msg == NULL) + goto err_ret; + + iccp_msg->buf = (char*) malloc(len); + if (iccp_msg->buf == NULL) + goto err_ret; + + memcpy(iccp_msg->buf, data, len); + iccp_msg->len = len; + *msg = iccp_msg; + + return 0; + +err_ret: + if(iccp_msg) + { + if(iccp_msg->buf) free(iccp_msg->buf); + free(iccp_msg); + } + + return -1; +} + +void iccp_csm_stp_role_count(struct CSM *csm) +{ + /* decide the role, lower ip to be active & socket client*/ + if(csm->role_type == STP_ROLE_NONE) + { + if(inet_addr(csm->sender_ip) < inet_addr(csm->peer_ip)) + { + /* Active*/ + ICCPD_LOG_INFO(__FUNCTION__, "Role: [Active]"); + csm->role_type = STP_ROLE_ACTIVE; + } + else + { + /* Standby*/ + ICCPD_LOG_INFO(__FUNCTION__, "Role [Standby]"); + csm->role_type = STP_ROLE_STANDBY; + } + } +} \ No newline at end of file diff --git a/src/iccpd/src/iccp_ifm.c b/src/iccpd/src/iccp_ifm.c new file mode 100644 index 000000000000..4c4ec49afdee --- /dev/null +++ b/src/iccpd/src/iccp_ifm.c @@ -0,0 +1,1037 @@ +/* +* iccp_ifm.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/iccp_cli.h" +#include "../include/logger.h" +#include "../include/mlacp_sync_update.h" +#include "../include/mlacp_link_handler.h" +#include "../include/port.h" +#include "../include/iccp_netlink.h" + +#define fwd_neigh_state_valid(state) (state & (NUD_REACHABLE|NUD_STALE|NUD_DELAY|NUD_PROBE|NUD_PERMANENT)) + +#ifndef MAX_BUFSIZE + #define MAX_BUFSIZE 4096 +#endif + +#ifndef NDA_RTA +#define NDA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#endif + +static int iccp_valid_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + unsigned int event = 0; + if (nlh->nlmsg_type != RTM_NEWLINK) + return 0; + + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) + ICCPD_LOG_ERR(__FUNCTION__, "Unknown message type."); + + return 0; +} + +/*Get kernel interfaces and ports during initialization*/ +int iccp_sys_local_if_list_get_init() +{ + struct System *sys = NULL; + struct nl_cb *cb; + struct nl_cb *orig_cb; + struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, + }; + int ret; + int retry = 1; + + if (!(sys = system_get_instance())) + return -1; + + while (retry) + { + retry = 0; + ret = nl_send_simple(sys->route_sock, RTM_GETLINK, NLM_F_DUMP, + &rt_hdr, sizeof(rt_hdr)); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); + return ret; + } + + orig_cb = nl_socket_get_cb(sys->route_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + { + ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); + return -ENOMEM; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_valid_handler, sys); + + ret = nl_recvmsgs(sys->route_sock, cb); + nl_cb_put(cb); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error. ret = %d errno = %d ",ret, errno); + if (ret != -NLE_DUMP_INTR) + return ret; + retry = 1; + } + } + + return ret; +} + +/*Handle arp received from kernel*/ +static int iccp_arp_valid_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + + do_one_neigh_request(nlh); + + return 0; +} + +/*Get kernel arp information during initialization*/ +int iccp_arp_get_init() +{ + struct System *sys = NULL; + struct nl_cb *cb; + struct nl_cb *orig_cb; + struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, + }; + int ret; + int retry = 1; + + if (!(sys = system_get_instance())) + return -1; + + while (retry) + { + retry = 0; + ret = nl_send_simple(sys->route_sock, RTM_GETNEIGH, NLM_F_DUMP, + &rt_hdr, sizeof(rt_hdr)); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); + return ret; + } + + orig_cb = nl_socket_get_cb(sys->route_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + { + ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); + return -ENOMEM; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_arp_valid_handler, sys); + + ret = nl_recvmsgs(sys->route_sock, cb); + nl_cb_put(cb); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error."); + if (ret != -NLE_DUMP_INTR) + return ret; + + retry = 1; + } + } + + return ret; +} + +/*When received ARP packets from kernel, update arp information*/ +void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct ARPMsg *arp_msg = NULL, *arp_info = NULL; + struct VLAN_ID *vlan_id_list = NULL; + struct Msg *msg_send = NULL; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *arp_lif = NULL; + uint8_t mac[ETHER_ADDR_LEN]; + + struct in_addr in_addr; + int verify_arp = 0; + int arp_update = 0; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf*/ + if (!(arp_lif = local_if_find_by_ifindex(ifindex))) + return; + + /* create ARP msg*/ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct ARPMsg); + arp_msg = (struct ARPMsg*) &buf; + arp_msg->op_type = ARP_SYNC_LIF; + sprintf(arp_msg->ifname, "%s", arp_lif->name); + memcpy(&arp_msg->ipv4_addr, &addr, 4); + memcpy(arp_msg->mac_addr, mac_addr, 6); + + /*Debug*/ + #if 1 + /* dump receive kernel ARP req*/ + fprintf(stderr, "\n======== Kernel ARP Update==========\n"); + fprintf(stderr, " Type = (New=%d)\n", RTM_NEWNEIGH); + fprintf(stderr, " ifindex = [%d] (%s)\n", ifindex, arp_lif->name); + fprintf(stderr, " IP = [%s]\n", show_ip_str(arp_msg->ipv4_addr)); + fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n", + arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3], + arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + fprintf(stderr, "==============================\n"); + #endif + + /* Find MLACP itf, member of port-channel*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if (!local_if_is_l3_mode(lif_po)) + { + /* Is the L2 MLAG itf belong to a vlan?*/ + LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) + { + if ( !(vlan_id_list->vlan_itf + && vlan_id_list->vlan_itf->ifindex == ifindex)) + continue; + break; + } + + if (!vlan_id_list) continue; + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", + lif_po->name, vlan_id_list->vlan_itf->name); + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf?*/ + if (ifindex != lif_po->ifindex) continue; + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", + lif_po->name); + } + + verify_arp = 1; + + break; + } + + if (lif_po) break; + } + + if (!(csm && lif_po)) return; + if (!verify_arp) return; + + /* update lif ARP*/ + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_info = (struct ARPMsg*) msg->buf; + if (arp_info->ipv4_addr != arp_msg->ipv4_addr) + continue; + + /* update ARP*/ + if(arp_info->op_type != arp_msg->op_type + || strcmp(arp_info->ifname, arp_msg->ifname)!=0 + || strncmp(arp_info->mac_addr, arp_msg->mac_addr, + ETHER_ADDR_LEN) != 0) + { + arp_update = 1; + arp_info->op_type = arp_msg->op_type; + sprintf(arp_info->ifname, "%s", arp_msg->ifname); + memcpy(arp_info->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + time(&arp_info->update_time); + + break; + } + + /* enquene lif_msg (add)*/ + if (!msg) + { + arp_msg->op_type = ARP_SYNC_LIF; + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) + { + mlacp_enqueue_arp(csm, msg); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + arp_msg->ifname, + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + arp_msg->ifname, + show_ip_str(arp_msg->ipv4_addr)); + } + + /* enqueue iccp_msg (add)*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + arp_msg->op_type = ARP_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + + return; +} + +static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct ARPMsg *arp_msg = NULL, *arp_info = NULL; + struct VLAN_ID *vlan_id_list = NULL; + struct Msg *msg_send = NULL; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *arp_lif = NULL; + uint8_t mac[ETHER_ADDR_LEN]; + + int verify_arp = 0; + int arp_update = 0; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf*/ + if (!(arp_lif = local_if_find_by_ifindex(ndm->ndm_ifindex))) + return; + + /* create ARP msg*/ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct ARPMsg); + arp_msg = (struct ARPMsg*) &buf; + arp_msg->op_type = ARP_SYNC_LIF; + sprintf(arp_msg->ifname, "%s", arp_lif->name); + if(tb[NDA_DST]) + memcpy(&arp_msg->ipv4_addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); + if (tb[NDA_LLADDR]) + memcpy(arp_msg->mac_addr, RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR])); + + + ICCPD_LOG_DEBUG(__FUNCTION__, "arp msg type %d , state (%04X)(%d) ifindex [%d] (%s) ip %s , mac [%02X:%02X:%02X:%02X:%02X:%02X] ", + msgtype, ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), + ndm->ndm_ifindex, arp_lif->name, + show_ip_str(arp_msg->ipv4_addr), + arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3],arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + + /*Debug*/ + #if 1 + /* dump receive kernel ARP req*/ + fprintf(stderr, "\n======== Kernel ARP ==========\n"); + fprintf(stderr, " Type = [%d] (New=%d, Del=%d)\n", msgtype, RTM_NEWNEIGH, RTM_DELNEIGH); + fprintf(stderr, " State = (%04X)(%d)\n", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state)); + fprintf(stderr, " ifindex = [%d] (%s)\n", ndm->ndm_ifindex, arp_msg->ifname); + fprintf(stderr, " IP = [%s]\n", show_ip_str(arp_msg->ipv4_addr)); + fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n", + arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3], + arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + fprintf(stderr, "==============================\n"); + #endif + + /* Find MLACP itf, member of port-channel*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if (!local_if_is_l3_mode(lif_po)) + { + /* Is the L2 MLAG itf belong to a vlan?*/ + LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) + { + if ( !(vlan_id_list->vlan_itf + && vlan_id_list->vlan_itf->ifindex == ndm->ndm_ifindex)) + continue; + break; + } + + if (!vlan_id_list) continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", + lif_po->name, vlan_id_list->vlan_itf->name); + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf?*/ + if (ndm->ndm_ifindex != lif_po->ifindex) continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", + lif_po->name); + } + + verify_arp = 1; + + break; + } + + if (lif_po) break; + } + + if (!(csm && lif_po)) return; + if (!verify_arp) return; + + /* update lif ARP*/ + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_info = (struct ARPMsg*) msg->buf; + if (arp_info->ipv4_addr != arp_msg->ipv4_addr) + continue; + + if (msgtype == RTM_DELNEIGH) + { + /* delete ARP*/ + TAILQ_REMOVE(&MLACP(csm).arp_list, msg, tail); + free(msg->buf); free(msg); msg = NULL; + ICCPD_LOG_DEBUG(__FUNCTION__, "Delete ARP %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + { + /* update ARP*/ + if(arp_info->op_type != arp_msg->op_type + || strcmp(arp_info->ifname, arp_msg->ifname)!=0 + || strncmp(arp_info->mac_addr, arp_msg->mac_addr, + ETHER_ADDR_LEN) != 0) + { + arp_update = 1; + arp_info->op_type = arp_msg->op_type; + sprintf(arp_info->ifname, "%s", arp_msg->ifname); + memcpy(arp_info->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + time(&arp_info->update_time); + } + break; + } + + if (msg && !arp_update) + return; + + if (msgtype != RTM_DELNEIGH) + { + /* enquene lif_msg (add)*/ + if (!msg) + { + arp_msg->op_type = ARP_SYNC_LIF; + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) + { + mlacp_enqueue_arp(csm, msg); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + arp_msg->ifname, + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + arp_msg->ifname, + show_ip_str(arp_msg->ipv4_addr)); + } + + /* enqueue iccp_msg (add)*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + arp_msg->op_type = ARP_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + + } + } + else + { + /* enqueue iccp_msg (delete)*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + arp_msg->op_type = ARP_SYNC_DEL; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[DEL] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[DEL] for %s", + show_ip_str(arp_msg->ipv4_addr)); + + } + } + + /*Debug: dump for dequeue ARP Info*/ + #if 1 + fprintf(stderr, "\n======== ARP Info List ========\n"); + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + fprintf(stderr, "type %d,ifname %s , ip %s\n", arp_msg->op_type, arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr)); + } + fprintf(stderr, "==============================\n"); + #endif + + /*TEST dump for dequeue ARP message*/ + #if 0 + while (MLACP(csm).arp_updated && !TAILQ_EMPTY(&(MLACP(csm).arp_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); + arp_msg = (struct ARPMsg *)msg->buf; + fprintf(stderr, "\n======== Dequeue ARP ========\n"); + fprintf(stderr, " Type = [%d]\n", arp_msg->op_type); + fprintf(stderr, " State = (%04X)(%d)\n", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state)); + fprintf(stderr, " ifname = [%s]\n", arp_msg->ifname); + fprintf(stderr, " IP = [%s]\n", show_ip_str(arp_msg->ipv4_addr)); + fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n", + arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3], + arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + fprintf(stderr, "==============================\n"); + free(msg->buf); + free(msg); + } + MLACP(csm).arp_updated = 0; + #endif + + return; +} + +void ifm_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, int len) +{ + while (RTA_OK (rta, len)) + { + if (rta->rta_type <= max) + tb[rta->rta_type] = rta; + rta = RTA_NEXT (rta, len); + } +} + +int do_one_neigh_request (struct nlmsghdr *n) +{ + struct ndmsg *ndm = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr * tb[NDA_MAX+1]; + + if (n->nlmsg_type == NLMSG_DONE) + { + return 0; + } + + /* process msg_type RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH */ + if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH ) + return(0); + + len -= NLMSG_LENGTH(sizeof(*ndm)); + if (len < 0) + return -1; + + ifm_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); + + if (ndm->ndm_state == NUD_INCOMPLETE + || ndm->ndm_state == NUD_FAILED + || ndm->ndm_state == NUD_NOARP + || ndm->ndm_state == NUD_PERMANENT + || ndm->ndm_state == NUD_NONE) + { + return(0); + } + + if (!tb[NDA_DST] || ndm->ndm_type != RTN_UNICAST) + { + return(0); + } + + if (ndm->ndm_family == AF_INET) + { + do_arp_request(ndm, tb, n->nlmsg_type); + } + + return(0); +} + +/*When received MAC add and del packets from mclagsyncd, update mac information*/ +void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uint8_t fdb_type, uint8_t op_type) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct MACMsg *mac_msg = NULL, *mac_info = NULL; + uint8_t mac_exist = 0; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *mac_lif = NULL; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf*/ + if (!(mac_lif = local_if_find_by_name(ifname))) + return; + + /* create MAC msg*/ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct MACMsg); + mac_msg = (struct MACMsg*) &buf; + mac_msg->op_type = op_type; + mac_msg->fdb_type = fdb_type; + sprintf(mac_msg->mac_str, "%s", mac_str); + mac_msg->vid = vid; + sprintf(mac_msg->ifname, "%s", mac_lif->name); + sprintf(mac_msg->origin_ifname, "%s", mac_lif->name); + mac_msg->age_flag = 0; + + /*Debug*/ + #if 1 + /* dump receive MAC info*/ + fprintf(stderr, "\n======== MAC Update==========\n"); + fprintf(stderr, " MAC = %s\n", mac_str); + fprintf(stderr, " ifname = %s\n", mac_lif->name); + fprintf(stderr, " vlan id = %d\n", vid); + fprintf(stderr, " fdb type = %s\n", fdb_type==MAC_TYPE_STATIC?"static":"dynamic"); + fprintf(stderr, " op type = %s\n", op_type==MAC_SYNC_ADD?"add":"del"); + fprintf(stderr, "==============================\n"); + #endif + + /* Find MLACP itf, must be mclag enabled port-channel*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + uint8_t find = 0; + + /*If MAC is from peer-link, break; peer-link is not in MLACP(csm).lif_list*/ + if (strcmp(ifname, csm->peer_itf_name) == 0) break; + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if(strcmp(lif_po->name, ifname) == 0) + { + find = 1; + break; + } + } + + if(find == 1) + break; + } + + if (!csm) return; + + /* find lif MAC+vid*/ + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_info = (struct MACMsg*) msg->buf; + + /*MAC and vid are equal*/ + if (strcmp(mac_info->mac_str, mac_str) == 0 && mac_info->vid== vid) + { + mac_exist = 1; + break; + } + } + + /*handle mac add*/ + if(op_type == MAC_SYNC_ADD) + { + /*same MAC exist*/ + if(mac_exist) + { + /*If the recv mac port is peer-link, that is add from iccpd, no need to handle*/ + if(strcmp(csm->peer_itf_name, mac_msg->ifname) == 0) + { + return; + } + + /*If the current mac port is peer-link, it will handle by port up event*/ + if(strcmp(csm->peer_itf_name, mac_info->ifname) == 0) + { + return; + } + + /* update MAC*/ + if(mac_info->fdb_type != mac_msg->fdb_type + || strcmp(mac_info->ifname, mac_msg->ifname) != 0 + || strcmp(mac_info->origin_ifname, mac_msg->ifname) != 0) + { + mac_info->fdb_type = mac_msg->fdb_type; + sprintf(mac_info->ifname, "%s", mac_msg->ifname); + sprintf(mac_info->origin_ifname, "%s", mac_msg->ifname); + + /*Remove MAC_AGE_LOCAL flag*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 0); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Update MAC for %s, ifname %s", mac_msg->mac_str, mac_msg->ifname); + } + else + { + /*All info are the same, Remove MAC_AGE_LOCAL flag, then return*/ + /*In theory, this will be happened that mac age and then learn*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 0); + + return; + } + } + else/*same MAC not exist*/ + { + /*If the portchannel the mac learn is change to down before the mac + sync to iccp, this mac must be deleted */ + if(mac_lif->state == PORT_STATE_DOWN) + { + del_mac_from_chip(mac_msg); + + return; + } + + /*set MAC_AGE_PEER flag before send this item to peer*/ + mac_msg->age_flag |= MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + mac_msg->op_type = MAC_SYNC_ADD; + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + struct Msg *msg_send = NULL; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, msg_len)==0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + + /*enqueue mac to mac-list*/ + if (iccp_csm_init_msg(&msg, (char*)mac_msg, msg_len)==0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); + + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-list enqueue: %s, add %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC %s, add %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + } + } + else/*handle mac del*/ + { + /*same MAC exist*/ + if(mac_exist) + { + if(strcmp(mac_info->ifname, csm->peer_itf_name) == 0) + { + /*peer-link learn mac is control by iccpd, ignore the chip del info*/ + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(peer-link), del %s vlan-id %d", + mac_info->ifname,mac_info->mac_str, mac_info->vid); + return; + } + + /*Add MAC_AGE_LOCAL flag*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 1); + + if(mac_info->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d", + mac_info->ifname,mac_info->mac_str, mac_info->vid); + + /*send mac del message to mclagsyncd.*/ + /*del_mac_from_chip(mac_info);*/ + + /*If local and peer both aged, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d, peer is not age", + mac_info->ifname,mac_info->mac_str, mac_info->vid); + + if(lif_po && lif_po->state == PORT_STATE_DOWN) + { + /*If local if is down, redirect the mac to peer-link*/ + memcpy(&mac_info->ifname, csm->peer_itf_name, IFNAMSIZ); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link", + mac_info->ifname,mac_info->mac_str, mac_info->vid); + } + + /*If local is aged but peer is not aged, Send mac add message to mclagsyncd*/ + mac_info->fdb_type = MAC_TYPE_DYNAMIC; + + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); + } + } + } + + return; +} + +void iccp_from_netlink_portchannel_state_handler( char * ifname, int state) +{ + struct CSM *csm = NULL; + struct LocalInterface *lif_po = NULL; + struct System *sys; + int po_is_active = 0; + + if((sys = system_get_instance()) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); + return; + } + + po_is_active = (state == PORT_STATE_UP); + + /* traverse all CSM */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if(lif_po->type == IF_T_PORT_CHANNEL && strncmp(lif_po->name, ifname, MAX_L_PORT_NAME) == 0) + { + mlacp_portchannel_state_handler(csm,lif_po,po_is_active); + } + } + } + /*peerlink state is sync by heardbeat, do not need to response */ + + return; +} + +int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, + int len, unsigned short flags) +{ + unsigned short type; + + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + + while (RTA_OK(rta, len)) + { + type = rta->rta_type & ~flags; + if ((type <= max) && (!tb[type])) + tb[type] = rta; + rta = RTA_NEXT(rta,len); + } + + return 0; +} + +int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) +{ + return parse_rtattr_flags(tb, max, rta, len, 0); +} + +void iccp_get_if_vlan_info_from_netlink() +{ + struct LocalInterface *lif = NULL; + struct { + struct nlmsghdr nlh; + struct ifinfomsg ifm; + /* attribute has to be NLMSG aligned */ + struct rtattr ext_req __attribute__ ((aligned(NLMSG_ALIGNTO))); + __u32 ext_filter_mask; + } req; + + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char * buf = malloc(10000000); + struct nl_sock *sk ; + int fd; + + struct System *sys; + + if((sys = system_get_instance()) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); + free(buf); + return; + } + fd = nl_socket_get_fd(sys->route_sock); + + memset(&req, 0, sizeof(req)); + req.nlh.nlmsg_len = sizeof(req); + req.nlh.nlmsg_type = RTM_GETLINK; + req.nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = 0; + req.ifm.ifi_family = PF_BRIDGE; + + req.ext_req.rta_type = IFLA_EXT_MASK; + req.ext_req.rta_len = RTA_LENGTH(sizeof(__u32)); + req.ext_filter_mask = RTEXT_FILTER_BRVLAN; + + send(fd, (void*)&req, sizeof(req), 0); + + iov.iov_base = buf; + while (1) + { + int status; + int msglen = 0; + + iov.iov_len = 10000000; + + status = recvmsg(fd, &msg, 0); + + if (status < 0 ||status == 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "netlink receive error (%d) status %d %d ", fd, status,errno); + free(buf); + return ; + } + + struct nlmsghdr *n = (struct nlmsghdr*)buf; + + msglen = status; + + while (NLMSG_OK(n, msglen)) + { + + struct ifinfomsg *ifm = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr * tb[IFLA_MAX+1]; + + if (n->nlmsg_type != RTM_NEWLINK) + { + free(buf); + return ; + } + + len -= NLMSG_LENGTH(sizeof(*ifm)); + if (len < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "BUG: wrong nlmsg len %d\n", len); + free(buf); + return ; + } + + if (ifm->ifi_family != AF_BRIDGE) + { + free(buf); + return ; + } + + if (lif = local_if_find_by_ifindex(ifm->ifi_index)) + { + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len); + + /* if AF_SPEC isn't there, vlan table is not preset for this port */ + if (!tb[IFLA_AF_SPEC]) + { + ICCPD_LOG_WARN(__FUNCTION__, "%d None\n", (ifm->ifi_index)); + free(buf); + return ; + } + else + { + struct rtattr *i, *list = tb[IFLA_AF_SPEC]; + int rem = RTA_PAYLOAD(list); + struct VLAN_ID *vlan = NULL; + + /*set vlan flag is removed*/ + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + vlan->vlan_removed = 1; + } + + for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) + { + struct bridge_vlan_info *vinfo; + + if (i->rta_type != IFLA_BRIDGE_VLAN_INFO) + continue; + + vinfo = RTA_DATA(i); + + local_if_add_vlan(lif, vinfo->vid); + + /*ICCPD_LOG_DEBUG(__FUNCTION__, "get vlan netlink msg lif index %d vinfo->flag %d, vid %d",ifm->ifi_index, vinfo->flags, vinfo->vid ); */ + } + + /*After update vlan list, remove unused item*/ + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if(vlan->vlan_removed == 1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Delete VLAN ID = %d from %s", vlan->vid, lif->name); + + LIST_REMOVE(vlan, port_next); + free(vlan); + } + } + } + } + + n = NLMSG_NEXT(n, msglen); + } + } + free(buf); +} + diff --git a/src/iccpd/src/iccp_main.c b/src/iccpd/src/iccp_main.c new file mode 100644 index 000000000000..f5a4fff3f275 --- /dev/null +++ b/src/iccpd/src/iccp_main.c @@ -0,0 +1,186 @@ +/* +* iccp_main.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include + +#include "../include/cmd_option.h" +#include "../include/logger.h" +#include "../include/scheduler.h" +#include "../include/system.h" + +int check_instance(char* pid_file_path) +{ + int pid_file = 0; + int rc = 0; + + if (pid_file_path == NULL) + return -1; + + pid_file = open(pid_file_path, O_CREAT | O_RDWR, 0666); + if(pid_file <=0 ) + { + fprintf(stderr, "Can't open a pid file. Terminate.\n"); + close(pid_file); + exit(EXIT_FAILURE); + } + + rc = flock(pid_file, LOCK_EX | LOCK_NB); + + if (rc) + { + if (errno == EWOULDBLOCK) + { + fprintf(stderr, "There is another instance running. Terminate.\n"); + close(pid_file); + exit(EXIT_FAILURE); + } + } + + return pid_file; +} + +void init_daemon(char* pid_file_path, int pid_file) +{ + pid_t pid, sid; + + pid = fork(); + if (pid < 0) + { + fprintf(stderr, "Failed to enter daemon mode: %s\n", strerror(errno)); + fprintf(stderr, "Please try to check your system resources.\n"); + close(pid_file); + unlink(pid_file_path); + exit(EXIT_FAILURE); + } + + if (pid > 0) + exit(EXIT_SUCCESS); + + umask(0); + sid = setsid(); + if (sid < 0) + { + fprintf(stderr, "Failed to create a new SID for this program: %s\n", strerror(errno)); + fprintf(stderr, "Please try to check your system resources.\n"); + close(pid_file); + unlink(pid_file_path); + exit(EXIT_FAILURE); + } + + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); +} + +#ifndef ICCPD_RUN_DIR +#define ICCPD_RUN_DIR "/var/run/iccpd/" +#endif + +static inline int iccpd_make_rundir(void) +{ + int ret; + + ret = mkdir(ICCPD_RUN_DIR, 0755); + if (ret && errno != EEXIST) + { + ICCPD_LOG_ERR(__FUNCTION__,"Failed to create directory \"%s\"", + ICCPD_RUN_DIR); + + return -errno; + } + + return 0; +} + +int main(int argc, char* argv[]) +{ + char *p; + int pid_file_fd = 0; + struct System* sys = NULL; + int err; + struct CmdOptionParser parser = CMD_OPTION_PARSER_INIT_VALUE; + + err = iccpd_make_rundir(); + if (err) + return 0; + + if (getuid() != 0) + { + fprintf(stderr, + "This program needs root permission to do device manipulation. " + "Please use sudo to execute it or change your user to root.\n"); + exit(EXIT_FAILURE); + } + + parser.init(&parser); + if (parser.parse(&parser, argc, argv) != 0) + { + parser.finalize(&parser); + return -1; + } + + pid_file_fd = check_instance(parser.pid_file_path); + if (pid_file_fd < 0) + { + fprintf(stderr, "Check instance with invalidate arguments, iccpd is terminated.\n"); + parser.finalize(&parser); + exit(EXIT_FAILURE); + } + + sys = system_get_instance(); + if (!sys) + { + fprintf(stderr, "Can't get a system instance, iccpd is terminated.\n"); + parser.finalize(&parser); + exit(EXIT_FAILURE); + } + + /*if(!parser.console_log) + init_daemon(parser.pid_file_path, pid_file_fd);*/ + + log_init(&parser); + + if (sys->log_file_path != NULL) + free(sys->log_file_path); + if (sys->cmd_file_path != NULL) + free(sys->cmd_file_path); + if (sys->config_file_path != NULL) + free(sys->config_file_path); + sys->log_file_path = strdup(parser.log_file_path); + sys->cmd_file_path = strdup(parser.cmd_file_path); + sys->config_file_path = strdup(parser.config_file_path); + sys->mclagdctl_file_path = strdup(parser.mclagdctl_file_path); + sys->pid_file_fd = pid_file_fd; + sys->telnet_port = parser.telnet_port; + parser.finalize(&parser); + + ICCPD_LOG_INFO(__FUNCTION__, "Iccpd is started, process id = %d.", getpid()); + scheduler_init(); + scheduler_start(); + scheduler_finalize(); + system_finalize(); + log_finalize(); + + return EXIT_SUCCESS; +} diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c new file mode 100644 index 000000000000..9f21bf0d5dfb --- /dev/null +++ b/src/iccpd/src/iccp_netlink.c @@ -0,0 +1,1136 @@ +/* +* iccp_netlink.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/iccp_ifm.h" +#include "../include/port.h" +#include "../include/iccp_csm.h" +#include "../include/logger.h" +#include "../include/scheduler.h" + +/** + * SECTION: Netlink helpers + */ + /* \cond HIDDEN_SYMBOLS */ +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +#define ARRAY_SIZE(array_name) (sizeof(array_name)/sizeof(array_name[0])) + +#ifndef NETLINK_BROADCAST_SEND_ERROR +#define NETLINK_BROADCAST_SEND_ERROR 0x4 +#endif + +static int iccp_ack_handler(struct nl_msg *msg, void *arg) +{ + bool *acked = arg; + + *acked = true; + + return NL_STOP; +} + +static int iccp_seq_check_handler(struct nl_msg *msg, void *arg) +{ + unsigned int *seq = arg; + struct nlmsghdr *hdr = nlmsg_hdr(msg); + + if (hdr->nlmsg_seq != *seq) + return NL_SKIP; + + return NL_OK; +} + +int iccp_send_and_recv(struct System *sys, struct nl_msg *msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) +{ + int ret; + struct nl_cb *cb; + struct nl_cb *orig_cb; + bool acked; + unsigned int seq = sys->genric_sock_seq++; + int err; + + ret = nl_send_auto(sys->genric_sock, msg); + nlmsg_free(msg); + if (ret < 0) + return ret; + + orig_cb = nl_socket_get_cb(sys->genric_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + return -ENOMEM; + + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, iccp_ack_handler, &acked); + nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, iccp_seq_check_handler, &seq); + if (valid_handler) + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); + + /* There is a bug in libnl. When implicit sequence number checking is in + * use the expected next number is increased when NLMSG_DONE is + * received. The ACK which comes after that correctly includes the + * original sequence number. However libnl is checking that number + * against the incremented one and therefore ack handler is never called + * and nl_recvmsgs finished with an error. To resolve this, custom + * sequence number checking is used here. + */ + + acked = false; + while (!acked) + { + ret = nl_recvmsgs(sys->genric_sock, cb); + if (ret) + { + err = ret; + goto put_cb; + } + } + + err = 0; +put_cb: + nl_cb_put(cb); + return err; +} + +int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, struct LocalInterface* local_if) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct nlattr *attrs[TEAM_ATTR_MAX + 1]; + struct nlattr *nl_port; + struct nlattr *port_attrs[TEAM_ATTR_PORT_MAX + 1]; + struct LocalInterface* lif = NULL; + struct LocalInterface* local_if_member = NULL; + struct CSM* csm; + int i; + uint32_t ifindex = 0; + struct System* sys = NULL; + char temp_buf[512]; + int len = 0; + + sys = system_get_instance(); + if (sys == NULL) + return 0; + + genlmsg_parse(nlh, 0, attrs, TEAM_ATTR_MAX, NULL); + + if (attrs[TEAM_ATTR_TEAM_IFINDEX]) + ifindex = nla_get_u32(attrs[TEAM_ATTR_TEAM_IFINDEX]); + + if(local_if == NULL) + local_if = local_if_find_by_ifindex(ifindex); + + if (!local_if) + return NL_SKIP; + + if (local_if->type != IF_T_PORT_CHANNEL) + return NL_SKIP; + + csm = local_if->csm; + + if(csm) + { + if (!attrs[TEAM_ATTR_LIST_PORT]) + return NL_SKIP; + + nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) + { + uint32_t member_index; + + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to parse nested attributes."); + return NL_SKIP; + } + + if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) + { + ICCPD_LOG_ERR(__FUNCTION__, "ifindex port attribute not found."); + return NL_SKIP; + } + + member_index = nla_get_u32(port_attrs[TEAM_ATTR_PORT_IFINDEX]); + + local_if_member = local_if_find_by_ifindex(member_index); + if(local_if_member == NULL) + { + + ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance (%d).", + local_if->name, member_index); + sys->need_sync_team_again = 1; + continue; + } + + if(port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) + { + local_if_member->po_id = -1; + mlacp_unbind_local_if(local_if_member); + } + else if ( local_if_member->po_id == -1) + { + local_if_member->po_id = local_if->po_id; + mlacp_bind_local_if(local_if->csm, local_if_member); + } + } + + memset(temp_buf, 0, 512); + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) + { + if(strlen(temp_buf) != 0) + len += snprintf(temp_buf + len, 512-len,"%s", ","); + + len += snprintf(temp_buf + len, 512-len,"%s",lif->name); + } + } + + if(strcmp(temp_buf,local_if->portchannel_member_buf)) + { + memset(local_if->portchannel_member_buf, 0, 512); + memcpy(local_if->portchannel_member_buf,temp_buf,sizeof(local_if->portchannel_member_buf)-1); + + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /* portchannel member changed, update port isolate attribute*/ + /*update_peerlink_isolate_from_all_csm_lif(csm); */ + csm->isolate_update_time = time(NULL); + } + } + } + else /*peerlink portchannel */ + { + if(local_if->is_peer_link) + { + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm->peer_link_if == local_if ) + { + break; + } + } + + if (csm == NULL) + return 0; + + nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) + { + uint32_t member_index; + + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to parse nested attributes."); + return NL_SKIP; + } + + if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) + { + ICCPD_LOG_WARN(__FUNCTION__, "ifindex port attribute not found."); + return NL_SKIP; + } + + member_index = nla_get_u32(port_attrs[TEAM_ATTR_PORT_IFINDEX]); + + local_if_member = local_if_find_by_ifindex(member_index); + if(local_if_member == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance (%d).", + local_if->name, member_index); + sys->need_sync_team_again = 1; + continue; + } + + if(port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) + { + local_if_member->po_id = -1; + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*link removed from portchannel, must be enabled mac learn*/ + set_peerlink_mlag_port_learn(local_if_member, 1); + } + + continue; + } + else if ( local_if_member->po_id == -1) + { + local_if_member->po_id = local_if->po_id; + + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*link add to portchannel, must be disabled mac learn*/ + set_peerlink_mlag_port_learn(local_if, 0); + } + } + } + + memset(temp_buf, 0, 512); + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) + { + if(strlen(temp_buf) != 0) + len += snprintf(temp_buf + len, 512-len,"%s", ","); + + len += snprintf(temp_buf + len, 512-len,"%s",lif->name); + } + } + + if(strcmp(temp_buf,local_if->portchannel_member_buf)) + { + memset(local_if->portchannel_member_buf, 0, 512); + memcpy(local_if->portchannel_member_buf,temp_buf,sizeof(local_if->portchannel_member_buf)-1); + + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*peerlink portchannel member changed*/ + /*update_peerlink_isolate_from_all_csm_lif(csm);*/ + csm->isolate_update_time = time(NULL); + } + } + } + } + + return 0; +} + +int iccp_get_port_member_list(struct LocalInterface* lif) +{ + struct System *sys; + struct nl_msg *msg; + int err; + + sys = system_get_instance(); + if(sys == NULL) + return 0; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + genlmsg_put(msg, NL_AUTO_PID, sys->genric_sock_seq, sys->family, 0, 0, + TEAM_CMD_PORT_LIST_GET, 0); + nla_put_u32(msg, TEAM_ATTR_TEAM_IFINDEX, lif->ifindex); + + err = iccp_send_and_recv(sys, msg, iccp_get_portchannel_member_list_handler, lif); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "recv msg err err = %d . errno = %d", err , errno); + return err; + } + + return 0; +} + +void update_local_system_id(struct LocalInterface* local_if) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if((sys = system_get_instance()) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); + return; + } + + if (local_if->type != IF_T_PORT_CHANNEL && local_if->po_id == -1) + return; + + /* traverse all CSM */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + /* sync system info from one port-channel device*/ + if(memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0 || + memcmp(MLACP(csm).remote_system.system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) + { + memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); + MLACP(csm).system_config_changed = 1; + + update_system_id(csm); + ICCPD_LOG_INFO(__FUNCTION__, + "update csm %d local system id to mac %02x:%02x:%02x:%02x:%02x:%02x of %s ", csm->mlag_id, local_if->mac_addr[0],local_if->mac_addr[1], + local_if->mac_addr[2],local_if->mac_addr[3],local_if->mac_addr[4],local_if->mac_addr[5], local_if->name ); + } + } + + return; +} + +void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link; + unsigned int *event = arg; + uint32_t ifindex; + char * ifname; + struct LocalInterface *lif = NULL; + struct nl_addr *nl_addr; + int addr_type = 0; + int op_state = 0; + + link = (struct rtnl_link *) obj; + ifindex = rtnl_link_get_ifindex(link); + op_state = rtnl_link_get_operstate(link); + ifname = rtnl_link_get_name(link); + nl_addr = rtnl_link_get_addr(link); + + if (nl_addr) + addr_type = nl_addr_guess_family(nl_addr); + + lif = local_if_find_by_ifindex(ifindex); + + if (!lif) + { + const itf_type_t if_whitelist[] = { + {"Po",IF_T_PORT_CHANNEL}, + {"Vl", IF_T_VLAN}, + {"Eth", IF_T_PORT}, + {NULL, 0} }; + int i = 0; + + for (i = 0; if_whitelist[i].ifname != NULL ; ++i) + { + if ((strncmp(ifname, + if_whitelist[i].ifname, strlen(if_whitelist[i].ifname)) == 0)) + { + lif = local_if_create(ifindex, ifname, if_whitelist[i].type); + + + lif->state = PORT_STATE_DOWN; + + if(IF_OPER_UP == op_state ) + { + lif->state = PORT_STATE_UP; + } + + switch (addr_type) + { + case AF_LLC: + memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); + update_local_system_id(lif); + default: + break; + } + + break; + } + } + } + else /*update*/ + { + /*update*/ + if(lif->state == PORT_STATE_DOWN && op_state == IF_OPER_UP) + { + lif->state = PORT_STATE_UP; + if(lif->type ==IF_T_PORT_CHANNEL) + iccp_from_netlink_portchannel_state_handler(lif->name, lif->state); + + ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); + } + else if (lif->state == PORT_STATE_UP && IF_OPER_UP != op_state) + { + lif->state = PORT_STATE_DOWN; + if(lif->type ==IF_T_PORT_CHANNEL) + iccp_from_netlink_portchannel_state_handler(lif->name, lif->state); + + ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); + } + + switch (addr_type) + { + case AF_LLC: + if (memcmp(nl_addr_get_binary_addr(nl_addr), lif->mac_addr, ETHER_ADDR_LEN) != 0) + { + memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); + lif->port_config_sync = 1; + + update_local_system_id(lif); + } + default: + break; + } + + /*sync port vlan info from kernel */ + if(lif && lif->type ==IF_T_PORT_CHANNEL && (*event)) + iccp_get_if_vlan_info_from_netlink(); + } + + return; +} + +void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link; + struct LocalInterface *lif; + uint32_t ifindex; + + link = (struct rtnl_link *) obj; + + ifindex = rtnl_link_get_ifindex(link); + if ((lif = local_if_find_by_ifindex(ifindex))) + local_if_destroy(lif->name); + + return; +} + + int iccp_local_if_addr_update(struct nl_msg *msg) + { + int len; + struct ifaddrmsg *ifa; + struct rtattr *tb[IFA_MAX + 1]; + struct LocalInterface *lif; + + struct nlmsghdr *n = nlmsg_hdr(msg); + + if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) + return 0; + + ifa = NLMSG_DATA (n); + + if (ifa->ifa_family != AF_INET ) + return 0; + + lif = local_if_find_by_ifindex(ifa->ifa_index); + if (!lif) + { + return 0; + } + + if (n->nlmsg_type == RTM_DELADDR) + { + lif->ipv4_addr = 0; + lif->prefixlen = 0; + lif->l3_mode = 0; + } + + len = n->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg)); + if (len < 0) + return 0; + + struct rtattr *rth = IFA_RTA(ifa); + int rtl = IFA_PAYLOAD(n); + + while (rtl && RTA_OK(rth, rtl)) + { + if (rth->rta_type == IFA_ADDRESS) + { + uint32_t ipaddr = htonl(*((uint32_t *)RTA_DATA(rth))); + lif->ipv4_addr = ipaddr; + lif->prefixlen = ifa->ifa_prefixlen; + lif->l3_mode = 1; + ICCPD_LOG_DEBUG(__FUNCTION__," if name %s index %d address %d.%d.%d.%d\n", + lif->name, + ifa->ifa_index , + (ipaddr >> 24) & 0xff, + (ipaddr >> 16) & 0xff, + (ipaddr >> 8) & 0xff, + ipaddr & 0xff); + } + rth = RTA_NEXT(rth, rtl); + } + + return 0; + } + + int iccp_sys_local_if_list_get_addr() +{ + struct System *sys = NULL; + struct nl_cb *cb; + struct nl_cb *orig_cb; + struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, + }; + int ret; + int retry = 1; + + if (!(sys = system_get_instance())) + return -1; + + while (retry) + { + retry = 0; + ret = nl_send_simple(sys->route_sock, RTM_GETADDR, NLM_F_DUMP, + &rt_hdr, sizeof(rt_hdr)); + + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); + return ret; + } + + orig_cb = nl_socket_get_cb(sys->route_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + { + ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); + return -ENOMEM; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_local_if_addr_update, sys); + ret = nl_recvmsgs(sys->route_sock, cb); + nl_cb_put(cb); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error ret = %d errno = %d .", ret, errno); + if (ret != -NLE_DUMP_INTR) + return ret; + retry = 1; + } + } + + return ret; +} + +static int iccp_route_event_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + unsigned int event = 1; + + switch (nlh->nlmsg_type) + { + case RTM_NEWLINK: + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type."); + break; + case RTM_DELLINK: + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_dellink, NULL) < 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type."); + break; + case RTM_NEWNEIGH: + case RTM_DELNEIGH: + do_one_neigh_request(nlh); + break; + case RTM_NEWADDR: + iccp_local_if_addr_update(msg); + break; + + default: + return NL_OK; + } + + return NL_STOP; +} + +/** + * SECTION: Context functions + */ +static int iccp_genric_event_handler(struct nl_msg *msg, void *arg) +{ + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + + switch (gnlh->cmd) + { + case TEAM_CMD_PORT_LIST_GET: + return iccp_get_portchannel_member_list_handler(msg, NULL); + } + + return NL_SKIP; +} + +/*init netlink socket*/ +int iccp_system_init_netlink_socket() +{ + struct System* sys = NULL; + int val = 0; + int grp_id = 0; + int err = 0; + int log_err_period = 0, log_err_time = 0; + + if ((sys = system_get_instance()) == NULL ) + return -1; + + sys->genric_sock = nl_socket_alloc(); + if (!sys->genric_sock) + goto err_genric_sock_alloc; + + sys->genric_sock_seq = time(NULL); + err = genl_connect(sys->genric_sock); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sock sys->genric_sock."); + goto err_genric_sock_connect; + } + + sys->genric_event_sock = nl_socket_alloc(); + if (!sys->genric_event_sock) + goto err_genric_event_sock_alloc; + + err = genl_connect(sys->genric_event_sock); + if(err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->genric_event_sock."); + goto err_genric_event_sock_connect; + } + + sys->route_sock = nl_cli_alloc_socket(); + if (!sys->route_sock) + goto err_route_sock_alloc; + err = nl_cli_connect(sys->route_sock, NETLINK_ROUTE); + if (err) + goto err_route_sock_connect; + + sys->route_event_sock = nl_socket_alloc(); + if (!sys->route_event_sock) + goto err_route_event_sock_alloc; + + err = nl_connect(sys->route_event_sock, NETLINK_ROUTE); + if(err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->route_event_sock. "); + goto err_route_event_sock_connect; + } + + err = nl_socket_set_buffer_size(sys->route_event_sock, 98304, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink route event sock."); + goto err_route_event_sock_connect; + } + + val = NETLINK_BROADCAST_SEND_ERROR; + err = setsockopt(nl_socket_get_fd(sys->genric_event_sock), SOL_NETLINK, + NETLINK_BROADCAST_ERROR, &val, sizeof(val)); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed set NETLINK_BROADCAST_ERROR on netlink event sock."); + goto err_return; + } + + err = nl_socket_set_buffer_size(sys->genric_sock, 98304, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink sock."); + goto err_return; + } + + err = nl_socket_set_buffer_size(sys->genric_event_sock, 98304, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink event sock."); + goto err_return; + } + + sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + while (sys->family < 0) + { + sleep(1); + log_err_period++; + /*If no portchannel configuration, teamd will not started, genl_ctrl_resolve() will return <0 forever */ + /*Only log error message 5 times*/ + if(log_err_period == 1 && log_err_time < 5) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink family. %d of TEAM_GENL_NAME %s ", sys->family, TEAM_GENL_NAME); + log_err_time++; + } + else + { + /*Log error message every 30s per time*/ + if(log_err_period == 30) + log_err_period = 0; + } + + sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + } + + grp_id = genl_ctrl_resolve_grp(sys->genric_sock, TEAM_GENL_NAME, + TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME); + if (grp_id < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink multicast groups. %d", grp_id); + goto err_return; + } + + err = nl_socket_add_membership(sys->genric_event_sock, grp_id); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + nl_socket_disable_seq_check(sys->genric_event_sock); + nl_socket_modify_cb(sys->genric_event_sock, NL_CB_VALID, NL_CB_CUSTOM, + iccp_genric_event_handler, sys); + + nl_socket_disable_seq_check(sys->route_event_sock); + nl_socket_modify_cb(sys->route_event_sock, NL_CB_VALID, NL_CB_CUSTOM, + iccp_route_event_handler, sys); + + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_NEIGH); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_LINK); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_IPV4_IFADDR); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + /*receive arp packet socket*/ + sys->arp_receive_fd = socket(PF_PACKET, SOCK_DGRAM, 0); + if (sys->arp_receive_fd < 0) + { + ICCPD_LOG_ERR(__FUNCTION__,"socket error "); + goto err_return; + } + + if (1) + { + struct sockaddr_ll sll; + memset(&sll, 0, sizeof(sll)); + sll.sll_family = AF_PACKET; + sll.sll_protocol = htons(ETH_P_ARP); + sll.sll_ifindex = 0; + if (bind(sys->arp_receive_fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) + { + ICCPD_LOG_ERR(__FUNCTION__,"socket bind error"); + goto err_return; + } + } + + goto succes_return; + +err_return: + +err_route_event_sock_connect: + nl_socket_free(sys->route_event_sock); + +err_route_sock_alloc: +err_route_sock_connect: + nl_socket_free(sys->route_sock); + +err_route_event_sock_alloc: +err_genric_event_sock_connect: + nl_socket_free(sys->genric_event_sock); + +err_genric_event_sock_alloc: +err_genric_sock_connect: + nl_socket_free(sys->genric_sock); + + return err; + +err_genric_sock_alloc: + +succes_return: + return 0; +} + +static int iccp_get_netlink_genic_sock_event_fd(struct System *sys) +{ + return nl_socket_get_fd(sys->genric_event_sock); +} + +static int iccp_netlink_genic_sock_event_handler(struct System *sys) +{ + int ret = 0; + + ret = nl_recvmsgs_default(sys->genric_event_sock); + if(ret) + { + sys->need_sync_team_again = 1; + ICCPD_LOG_DEBUG(__FUNCTION__, "genric_event_sock %d recvmsg error ret = %d ",nl_socket_get_fd(sys->genric_event_sock), ret); + } + + return ret; +} + +static int iccp_get_netlink_route_sock_event_fd(struct System *sys) +{ + return nl_socket_get_fd(sys->route_event_sock); +} + +static int iccp_get_receive_arp_packet_sock_fd(struct System *sys) +{ + return sys->arp_receive_fd; +} + +static int iccp_receive_arp_packet_handler(struct System *sys) +{ + unsigned char buf[1024]; + struct sockaddr_ll sll; + socklen_t sll_len = sizeof(sll); + struct arphdr *a = (struct arphdr*)buf; + int n; + unsigned int ifindex; + unsigned int addr; + uint8_t mac_addr[ETHER_ADDR_LEN]; + + n = recvfrom(sys->arp_receive_fd, buf, sizeof(buf), MSG_DONTWAIT, + (struct sockaddr*)&sll, &sll_len); + if (n < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "arp recvfrom: %s",buf); + return -1; + } + + /* Sanity checks */ + if (n < sizeof(*a) || + (a->ar_op != htons(ARPOP_REQUEST) && + a->ar_op != htons(ARPOP_REPLY)) || + a->ar_pln != 4 || + a->ar_pro != htons(ETH_P_IP) || + a->ar_hln != sll.sll_halen || + sizeof(*a) + 2*4 + 2*a->ar_hln > n) + return -1; + + /*Only process ARPOP_REPLY*/ + if(a->ar_op == htons(ARPOP_REQUEST)) + return 0; + + ifindex = sll.sll_ifindex; + memcpy(mac_addr, (char*)(a+1), 6); + memcpy(&addr, (char*)(a+1) + a->ar_hln, 4); + + do_arp_update (ifindex, addr, mac_addr); + + return 0; +} + +static int iccp_netlink_route_sock_event_handler(struct System *sys) +{ + int ret = 0; + + ret = nl_recvmsgs_default(sys->route_event_sock); + + if(ret) + { + sys->need_sync_netlink_again = 1; + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d recvmsg error ret = %d errno = %d ",nl_socket_get_fd(sys->route_event_sock), ret, errno); + } + + return ret; +} + +void iccp_netlink_sync_again() +{ + struct System* sys = NULL; + struct LocalInterface* lif = NULL; + + if ((sys = system_get_instance()) == NULL ) + return ; + + if(sys->need_sync_netlink_again) + { + sys->need_sync_netlink_again = 0; + + /*Get kernel interface and port */ + iccp_sys_local_if_list_get_init(); + } + + if(sys->need_sync_team_again) + { + sys->need_sync_team_again = 0; + + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->type == IF_T_PORT_CHANNEL) + { + iccp_get_port_member_list(lif); + } + } + } + + return; +} + +extern int iccp_get_receive_fdb_sock_fd(struct System *sys); +extern int iccp_receive_fdb_handler_from_syncd(struct System *sys); + +/* cond HIDDEN_SYMBOLS */ +struct iccp_eventfd { + int (*get_fd)(struct System* sys); + int (*event_handler)(struct System* sys); +}; +/* endcond */ + +static const struct iccp_eventfd iccp_eventfds[] = { + { + .get_fd = iccp_get_server_sock_fd, + .event_handler = scheduler_server_accept, + }, + { + .get_fd = iccp_get_netlink_genic_sock_event_fd, + .event_handler = iccp_netlink_genic_sock_event_handler, + }, + { + .get_fd = iccp_get_netlink_route_sock_event_fd, + .event_handler = iccp_netlink_route_sock_event_handler, + }, + { + .get_fd = iccp_get_receive_arp_packet_sock_fd, + .event_handler = iccp_receive_arp_packet_handler, + } +}; + +/* \cond HIDDEN_SYMBOLS */ +#define ICCP_EVENT_FDS_COUNT ARRAY_SIZE(iccp_eventfds) +/* \endcond */ +/* +@return fd. + * + **/ + +int iccp_get_eventfd_fd(struct System *sys) +{ + return sys->epoll_fd; +} + +int iccp_init_netlink_event_fd(struct System *sys) +{ + int efd; + int i; + struct epoll_event event; + int err; + + efd = epoll_create1(0); + if (efd == -1) + return -errno; + for (i = 0; i < ICCP_EVENT_FDS_COUNT; i++) + { + int fd = iccp_eventfds[i].get_fd(sys); + + event.data.fd = fd; + event.events = EPOLLIN; + err = epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event); + if (err == -1) + { + err = -errno; + goto close_efd; + } + } + + sys->epoll_fd = efd; + + return 0; + +close_efd: + close(efd); + + return err; +} + +/** + * + * @details Handler events which happened on event filedescriptor. + * + * @return Zero on success or negative number in case of an error. + **/ + +int iccp_handle_events(struct System * sys) +{ + struct epoll_event events[ICCP_EVENT_FDS_COUNT+sys->readfd_count]; + struct CSM* csm = NULL; + int nfds; + int n; + int i; + int err; + int max_nfds; + max_nfds = ICCP_EVENT_FDS_COUNT+sys->readfd_count; + + nfds = epoll_wait(sys->epoll_fd, events, max_nfds, EPOLL_TIMEOUT_MSEC); + + /* Go over list of event fds and handle them sequentially */ + for (i = 0; i < nfds; i++) + { + for (n = 0; n < ICCP_EVENT_FDS_COUNT; n++) + { + const struct iccp_eventfd *eventfd = &iccp_eventfds[n]; + if (events[i].data.fd == eventfd->get_fd(sys)) + { + err = eventfd->event_handler(sys); + if (err) + ICCPD_LOG_INFO(__FUNCTION__, "Scheduler fd %d handler error %d !",events[i].data.fd, err ); + break; + } + } + + if (n < ICCP_EVENT_FDS_COUNT) + continue; + + if (events[i].data.fd == sys->sync_ctrl_fd) + { + int client_fd = mclagd_ctl_sock_accept(sys->sync_ctrl_fd); + if (client_fd > 0) + { + mclagd_ctl_interactive_process(client_fd); + close(client_fd); + } + continue; + } + + if (events[i].data.fd == sys->sync_fd) + { + iccp_receive_fdb_handler_from_syncd(sys); + + continue; + } + + if (FD_ISSET(events[i].data.fd, &sys->readfd)) + { + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm->sock_fd == events[i].data.fd ) + { + scheduler_csm_read_callback(csm); + break; + } + } + } + } + + return 0; +} + diff --git a/src/iccpd/src/logger.c b/src/iccpd/src/logger.c new file mode 100644 index 000000000000..c495b3452ebb --- /dev/null +++ b/src/iccpd/src/logger.c @@ -0,0 +1,124 @@ +/* +* logger.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ +#include +#include +#include +#include + +#include "../include/cmd_option.h" +#include "../include/logger.h" + +static uint32_t _iccpd_log_level_map[] = +{ + LOG_DEBUG, + LOG_INFO, + LOG_NOTICE, + LOG_WARNING, + LOG_ERR, + LOG_CRIT, +}; + +static char* log_level_to_string(int level) +{ + switch (level) + { + case CRITICAL_LOG_LEVEL: + return "CRITICAL"; + case ERR_LOG_LEVEL: + return "ERROR"; + case WARN_LOG_LEVEL: + return "WARN"; + case NOTICE_LOG_LEVEL: + return "NOTICE"; + case INFO_LOG_LEVEL: + return "INFO"; + case DEBUG_LOG_LEVEL: + return "DEBUG"; + } + + return "INFO"; +} + +struct LoggerConfig* logger_get_configuration() +{ + static struct LoggerConfig config; + + if (config.init == 0) + { + config.console_log_enabled = 0; + config.log_level = DEBUG_LOG_LEVEL; + config.init = 1; + } + + return &config; +} + +void log_init(struct CmdOptionParser* parser) +{ + struct LoggerConfig* config = logger_get_configuration(); + config->console_log_enabled = parser->console_log; +} + +void log_finalize() +{ + /*do nothing*/ +} + +void write_log(const int level, const char* tag, const char* format, ...) +{ + struct LoggerConfig* config = logger_get_configuration(); + char buf[LOGBUF_SIZE]; + va_list args; + unsigned int prefix_len; + unsigned int avbl_buf_len; + unsigned int print_len; + +#if 0 + if (!config->console_log_enabled) + return; +#endif + + if (level < config->log_level) + return; + + prefix_len = snprintf(buf, LOGBUF_SIZE, "[%s.%s] ", tag, log_level_to_string(level)); + avbl_buf_len = LOGBUF_SIZE - prefix_len; + + va_start(args, format); + print_len = vsnprintf(buf + prefix_len, avbl_buf_len, format, args); + va_end(args); + + /* Since osal_vsnprintf doesn't always return the exact size written to the buffer, + * we must check if the user string length exceeds the remaing buffer size. + */ + if (print_len > avbl_buf_len) + { + print_len = avbl_buf_len; + } + + buf[prefix_len+print_len] = '\0'; + ICCPD_UTILS_SYSLOG(_iccpd_log_level_map[level], "%s", buf); + + return; +} + diff --git a/src/iccpd/src/mclagdctl/Makefile b/src/iccpd/src/mclagdctl/Makefile new file mode 100644 index 000000000000..5520da22cee2 --- /dev/null +++ b/src/iccpd/src/mclagdctl/Makefile @@ -0,0 +1,28 @@ + + +C = gcc +SOURCES = \ +mclagdctl.c + +OBJECTS = \ +mclagdctl.o + +HEADERS = \ +mclagdctl.h + +CFLAGS = -g -O2 -fstack-protector-strong -Wformat -Werror=format-security +LDFLAGS = +LDADD = + +all: mclagdctl + +%.o: %.c $(HEADERS) + +mclagdctl: $(OBJECTS) + $(CC) -o ./mclagdctl $(OBJECTS) $(LDFLAGS) + +.PHONY: clean +clean: + -rm -f $(OBJECTS) ./mclagdctl + + diff --git a/src/iccpd/src/mclagdctl/mclagdctl b/src/iccpd/src/mclagdctl/mclagdctl new file mode 100755 index 0000000000000000000000000000000000000000..5e878b720e6d0f14e94aa1dc0b26416216fc7c5b GIT binary patch literal 46856 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 vCdyzGD)mK~kb=E;Dftt+{WKjez<. +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: Jim Jiang from nephos +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mclagdctl.h" + +static int mclagdctl_sock_fd = -1; +char *mclagdctl_sock_path = "/var/run/iccpd/mclagdctl.sock"; + +/* +Already implemented command: +mclagdctl -i dump state +mclagdctl -i dump arp +mclagdctl -i dump mac +mclagdctl -i dump portlist local +mclagdctl -i dump portlist peer +*/ + +static struct command_type command_types[] = +{ + { + .id = ID_CMDTYPE_D, + .name = "dump", + .enca_msg = NULL, + .parse_msg = NULL, + }, + { + .id = ID_CMDTYPE_D_S, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_STATE, + .name = "state", + .enca_msg = mclagdctl_enca_dump_state, + .parse_msg = mclagdctl_parse_dump_state, + }, + { + .id = ID_CMDTYPE_D_A, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_ARP, + .name = "arp", + .enca_msg = mclagdctl_enca_dump_arp, + .parse_msg = mclagdctl_parse_dump_arp, + }, + { + .id = ID_CMDTYPE_D_A, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_MAC, + .name = "mac", + .enca_msg = mclagdctl_enca_dump_mac, + .parse_msg = mclagdctl_parse_dump_mac, + }, + { + .id = ID_CMDTYPE_D_P, + .parent_id = ID_CMDTYPE_D, + .name = "portlist", + }, + { + .id = ID_CMDTYPE_D_P_L, + .parent_id = ID_CMDTYPE_D_P, + .info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST, + .name = "local", + .enca_msg = mclagdctl_enca_dump_local_portlist, + .parse_msg = mclagdctl_parse_dump_local_portlist, + }, + { + .id = ID_CMDTYPE_D_P_P, + .parent_id = ID_CMDTYPE_D_P, + .info_type = INFO_TYPE_DUMP_PEER_PORTLIST, + .name = "peer", + .enca_msg = mclagdctl_enca_dump_peer_portlist, + .parse_msg = mclagdctl_parse_dump_peer_portlist, + }, +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define COMMAND_TYPE_COUNT ARRAY_SIZE(command_types) + +int mclagdctl_sock_connect() +{ + struct sockaddr_un addr; + int addrlen = 0; + int ret = 0; + + if(mclagdctl_sock_fd >= 0) + return 0; + + if(strlen(mclagdctl_sock_path) <= 0) + return -1; + + mclagdctl_sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); + + if(mclagdctl_sock_fd < 0) + { + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "%s", mclagdctl_sock_path); + addrlen = sizeof(addr.sun_family) + strlen(mclagdctl_sock_path); + + if((ret = connect(mclagdctl_sock_fd, (struct sockaddr*)&addr, addrlen)) < 0) + { + close(mclagdctl_sock_fd); + mclagdctl_sock_fd = -1; + return -1; + } + + return 0; +} + +void mclagdctl_sock_close() +{ + if(mclagdctl_sock_fd > 0) + { + close(mclagdctl_sock_fd); + mclagdctl_sock_fd = -1; + } + + return; +} + +int mclagdctl_sock_write(int fd, unsigned char *w_buf ,int total_len) +{ + int write_len =0; + int ret=0; + + while(write_len < total_len) + { + ret = write(fd, w_buf + write_len, total_len - write_len); + if(ret <= 0) + { + return 0; + } + write_len += ret; + } + + return write_len; +} + +int mclagdctl_sock_read(int fd, unsigned char *r_buf ,int total_len) +{ + int read_len=0; + int ret=0; + struct timeval tv = {0}; + fd_set read_fd; + + while(read_len < total_len) + { + FD_ZERO(&read_fd); + FD_SET(fd, &read_fd); + tv.tv_sec = 10; + tv.tv_usec = 0; + + switch ((ret = select(fd + 1, &read_fd, NULL, NULL, &tv))) + { + case -1:// error + fprintf(stdout, "Mclagdctl:Select return error:%s\n", strerror(errno)); + return -1; + case 0:// timeout + fprintf(stdout, "Mclagdctl:Select timeout:%s\n", strerror(errno)); + return -1; + default: + break; + } + + ret = read(fd, r_buf + read_len, total_len - read_len); + if(ret <= 0) + { + return -1; + } + read_len += ret; + } + + return read_len; +} + +int mclagdctl_enca_dump_state(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_STATE; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_state(char *msg, int data_len) +{ + struct mclagd_state * state_info = NULL; + int len = 0; + int count = 0; + int pos = 0; + + len = sizeof (struct mclagd_state); + + for (; data_len >= len; data_len -=len, count ++) + { + state_info = (struct mclagd_state*)(msg + len * count); + + fprintf(stdout,"%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR"); + + if (state_info->mclag_id <= 0) + fprintf(stdout,"%s: %s\n", "Mclag id", "UNKNOWN"); + else + fprintf(stdout,"%s: %d\n" ,"Mclag id", state_info->mclag_id); + + fprintf(stdout,"%s: %s\n", "Local Ip", state_info->local_ip); + fprintf(stdout,"%s: %s\n", "Peer Ip", state_info->peer_ip); + fprintf(stdout,"%s: %s\n", "Peer Link Interface", state_info->peer_link_if); + + fprintf(stdout,"%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "Peer Link Mac", + state_info->peer_link_mac[0], state_info->peer_link_mac[1], + state_info->peer_link_mac[2], state_info->peer_link_mac[3], + state_info->peer_link_mac[4], state_info->peer_link_mac[5]); + + if (state_info->role == 0) + fprintf(stdout,"%s: %s\n", "Role", "NONE"); + else if (state_info->role == 1) + fprintf(stdout,"%s: %s\n", "Role", "ACTIVE"); + else if (state_info->role == 2) + fprintf(stdout,"%s: %s\n", "Role", "STANDBY"); + + fprintf(stdout,"%s: %s\n", "Enabled PortChannel", state_info->enabled_po); + + } + + return 0; +} + +int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return -1; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_ARP; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_arp(char *msg, int data_len) +{ + struct mclagd_arp_msg * arp_info = NULL; + int len = 0; + int count = 0; + + fprintf(stdout, "%-6s", "No."); + fprintf(stdout, "%-20s", "IP"); + fprintf(stdout, "%-20s", "MAC"); + fprintf(stdout, "%-20s", "DEV"); + fprintf(stdout, "\n"); + + len = sizeof (struct mclagd_arp_msg); + + for (; data_len >= len; data_len -=len, count ++) + { + arp_info = (struct mclagd_arp_msg*)(msg + len * count); + + fprintf(stdout, "%-6d", count+1); + fprintf(stdout, "%-20s", arp_info->ipv4_addr); + fprintf(stdout,"%02x:%02x:%02x:%02x:%02x:%02x", + arp_info->mac_addr[0], arp_info->mac_addr[1], + arp_info->mac_addr[2], arp_info->mac_addr[3], + arp_info->mac_addr[4], arp_info->mac_addr[5]); + fprintf(stdout, " "); + fprintf(stdout, "%-20s", arp_info->ifname); + fprintf(stdout, "\n"); + } + + return 0; +} + +int mclagdctl_enca_dump_mac(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return -1; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_MAC; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_mac(char *msg, int data_len) +{ + struct mclagd_mac_msg * mac_info = NULL; + int len = 0; + int count = 0; + + fprintf(stdout, "%-60s\n", "TYPE: S-STATIC, D-DYNAMIC; AGE: L-Local age, P-Peer age"); + + fprintf(stdout, "%-6s", "No."); + fprintf(stdout, "%-5s", "TYPE"); + fprintf(stdout, "%-20s", "MAC"); + fprintf(stdout, "%-5s", "VID"); + fprintf(stdout, "%-20s", "DEV"); + fprintf(stdout, "%-20s", "ORIGIN-DEV"); + fprintf(stdout, "%-5s", "AGE"); + fprintf(stdout, "\n"); + + len = sizeof (struct mclagd_mac_msg); + + for (; data_len >= len; data_len -=len, count ++) + { + mac_info = (struct mclagd_mac_msg*)(msg + len * count); + + fprintf(stdout, "%-6d", count + 1); + + if(mac_info->fdb_type == MAC_TYPE_STATIC_CTL) + fprintf(stdout, "%-5s", "S"); + else + fprintf(stdout, "%-5s", "D"); + + fprintf(stdout, "%-20s", mac_info->mac_str); + fprintf(stdout, "%-5d", mac_info->vid); + fprintf(stdout, "%-20s", mac_info->ifname); + fprintf(stdout, "%-20s", mac_info->origin_ifname); + + if((mac_info->age_flag & MAC_AGE_LOCAL_CTL) && (mac_info->age_flag & MAC_AGE_PEER_CTL)) + fprintf(stdout, "%-5s", "LP"); + else if(mac_info->age_flag & MAC_AGE_LOCAL_CTL) + fprintf(stdout, "%-5s", "L"); + else if(mac_info->age_flag & MAC_AGE_PEER_CTL) + fprintf(stdout, "%-5s", "P"); + else + fprintf(stdout, "%-5s", " "); + fprintf(stdout, "\n"); + } + + return 0; +} + +int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return -1; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_local_portlist(char *msg, int data_len) +{ + struct mclagd_local_if * lif_info = NULL; + int len = 0; + int count = 0; + int pos = 0; + + len = sizeof (struct mclagd_local_if); + + for (; data_len >= len; data_len -=len, count ++) + { + lif_info = (struct mclagd_local_if*)(msg + len * count); + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + fprintf(stdout, "\n"); + + if (memcmp(lif_info->type, "PORT-CHANNEL", 12) == 0) + { + fprintf(stdout,"%s: %d\n" ,"Ifindex", lif_info->ifindex); + fprintf(stdout,"%s: %s\n", "Type", lif_info->type); + fprintf(stdout,"%s: %s\n", "PortName", lif_info->name); + fprintf(stdout,"%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "MAC", + lif_info->mac_addr[0], lif_info->mac_addr[1], + lif_info->mac_addr[2], lif_info->mac_addr[3], + lif_info->mac_addr[4], lif_info->mac_addr[5]); + + fprintf(stdout,"%s: %s\n", "IPv4Address", lif_info->ipv4_addr); + fprintf(stdout,"%s: %d\n" ,"Prefixlen", lif_info->prefixlen); + fprintf(stdout,"%s: %s\n", "State", lif_info->state); + fprintf(stdout,"%s: %d\n" ,"L3Mode", lif_info->l3_mode); + fprintf(stdout,"%s: %d\n" ,"IsPeerlink", lif_info->is_peer_link); + fprintf(stdout,"%s: %s\n", "PortchannelMem", lif_info->portchannel_member_buf); + fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); + fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", lif_info->po_active); + fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state); + fprintf(stdout,"%s: %d\n" ,"IsIsolateWithPeerlink", lif_info->isolate_to_peer_link); + fprintf(stdout,"%s: %s\n" ,"VlanList", lif_info->vlanlist); + } + else + { + fprintf(stdout,"%s: %d\n" ,"Ifindex", lif_info->ifindex); + fprintf(stdout,"%s: %s\n", "Type", lif_info->type); + fprintf(stdout,"%s: %s\n", "PortName", lif_info->name); + fprintf(stdout,"%s: %s\n", "State", lif_info->state); + fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); + } + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + + fprintf(stdout, "\n\n"); + } + + return 0; +} + +int mclagdctl_enca_dump_peer_portlist(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return -1; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_PEER_PORTLIST; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len) +{ + struct mclagd_peer_if * pif_info = NULL; + int len = 0; + int count = 0; + int pos = 0; + + len = sizeof (struct mclagd_peer_if); + + for (; data_len >= len; data_len -=len, count ++) + { + pif_info = (struct mclagd_peer_if*)(msg + len * count); + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + fprintf(stdout, "\n"); + + fprintf(stdout,"%s: %d\n" ,"Ifindex", pif_info->ifindex); + fprintf(stdout,"%s: %s\n", "Type", pif_info->type); + fprintf(stdout,"%s: %s\n", "PortName", pif_info->name); + fprintf(stdout,"%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "MAC", + pif_info->mac_addr[0], pif_info->mac_addr[1], + pif_info->mac_addr[2], pif_info->mac_addr[3], + pif_info->mac_addr[4], pif_info->mac_addr[5]); + + fprintf(stdout,"%s: %s\n", "State", pif_info->state); + fprintf(stdout,"%s: %d\n" ,"PortchannelId", pif_info->po_id); + fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", pif_info->po_active); + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + + fprintf(stdout, "\n\n"); + } + + return 0; +} + +static bool __mclagdctl_cmd_executable(struct command_type *cmd_type) +{ + if (!cmd_type->enca_msg || !cmd_type->parse_msg) + return 0; + + return 1; +} + +static int __mclagdctl_cmd_param_cnt(struct command_type *cmd_type) +{ + int i = 0; + while (cmd_type->params[i]) + i++; + + return i; +} + +static struct command_type *__mclagdctl_get_cmd_by_parent(char *cmd_name, + enum id_command_type parent_id) +{ + int i; + + for (i = 0; i < COMMAND_TYPE_COUNT; i++) + { + if (!strncmp(command_types[i].name, cmd_name, strlen(cmd_name)) + && command_types[i].parent_id == parent_id) + return &command_types[i]; + } + + return NULL; +} + +static struct command_type *__mclagdctl_get_cmd_by_id(enum id_command_type id) +{ + int i; + + for (i = 0; i < COMMAND_TYPE_COUNT; i++) + { + if (command_types[i].id == id) + return &command_types[i]; + } + + return NULL; +} + +static int mclagdctl_find_cmd(struct command_type **pcmd_type, int *argc, char ***argv) +{ + char *cmd_name; + enum id_command_type parent_id = ID_CMDTYPE_NONE; + struct command_type *cmd_type; + + while (1) + { + if (!*argc) + { + fprintf(stderr, "None or incomplete command\n"); + return -EINVAL; + } + + cmd_name = *argv[0]; + (*argc)--; + (*argv)++; + cmd_type = __mclagdctl_get_cmd_by_parent(cmd_name, parent_id); + + if (!cmd_type) + { + fprintf(stderr, "Unknown command \"%s\".\n", cmd_name); + return -EINVAL; + } + + if (__mclagdctl_cmd_executable(cmd_type) && __mclagdctl_cmd_param_cnt(cmd_type) >= *argc) + { + *pcmd_type = cmd_type; + return 0; + } + + parent_id = cmd_type->id; + } +} + +static int mclagdctl_check_cmd_params(struct command_type *cmd_type, + int argc, char **argv) +{ + int i = 0; + + while (cmd_type->params[i]) + { + if (i == argc) + { + fprintf(stderr, "Command line parameter \"%s\" expected.\n", cmd_type->params[i]); + return -EINVAL; + } + i++; + } + return 0; +} + +static void mclagdctl_print_cmd(struct command_type *cmd_type) +{ + if (cmd_type->parent_id != ID_CMDTYPE_NONE) { + mclagdctl_print_cmd(__mclagdctl_get_cmd_by_id(cmd_type->parent_id)); + fprintf(stdout, " "); + } + fprintf(stdout, "%s", cmd_type->name); +} + +static void mclagdctl_print_help(const char *argv0) +{ + int i, j; + struct command_type *cmd_type; + + fprintf(stdout, "%s [options] command [command args]\n" + " -h --help Show this help\n" + " -i --mclag-id Specify one mclag id\n", + argv0); + fprintf(stdout, "Commands:\n"); + for (i = 0; i < COMMAND_TYPE_COUNT; i++) + { + cmd_type = &command_types[i]; + if (!__mclagdctl_cmd_executable(cmd_type)) + continue; + fprintf(stdout, " "); + mclagdctl_print_cmd(cmd_type); + for (j = 0; cmd_type->params[j]; j++) + fprintf(stdout, " %s", cmd_type->params[j]); + fprintf(stdout, "\n"); + } +} + +int main(int argc, char **argv) +{ + char buf[MCLAGDCTL_CMD_SIZE]= {0}; + char *argv0 = argv[0]; + char *rcv_buf = NULL; + static const struct option long_options[] = + { + { "help", no_argument, NULL, 'h' }, + { "mclag id", required_argument, NULL, 'i' }, + { NULL, 0, NULL, 0 } + }; + int opt; + int err; + struct command_type *cmd_type; + int ret; + unsigned mclag_id = 0; + int len = 0; + char *data; + struct mclagd_reply_hdr *reply; + + while ((opt = getopt_long(argc, argv, "hi:", long_options, NULL)) >= 0) + { + switch(opt) + { + case 'h': + mclagdctl_print_help(argv0); + return EXIT_SUCCESS; + case 'i': + mclag_id = atoi (optarg); + break; + case '?': + fprintf(stderr, "unknown option.\n"); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + default: + fprintf(stderr, "unknown option \"%c\".\n", opt); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + } + + argv += optind; + argc -= optind; + + err = mclagdctl_find_cmd(&cmd_type, &argc, &argv); + if (err) + { + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + + err = mclagdctl_check_cmd_params(cmd_type, argc, argv); + if (err) + { + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + + if (mclagdctl_sock_fd <= 0) + { + ret = mclagdctl_sock_connect(); + if(ret < 0) + return EXIT_FAILURE; + } + + if (cmd_type->enca_msg(buf, mclag_id, argc, argv) < 0) + { + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + ret = mclagdctl_sock_write(mclagdctl_sock_fd, buf, sizeof(struct mclagdctl_req_hdr)); + + if(ret <= 0) + { + fprintf(stderr, "Failed to send command to mclagd\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + /*read data length*/ + memset(buf, 0, MCLAGDCTL_CMD_SIZE); + ret = mclagdctl_sock_read(mclagdctl_sock_fd, buf, sizeof(int)); + if(ret <= 0) + { + fprintf(stderr, "Failed to read data length from mclagd\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + /*cont length*/ + len = *((int*)buf); + if(len <= 0) + { + ret = EXIT_FAILURE; + fprintf(stderr, "pkt len = %d, error\n", len); + goto mclagdctl_disconnect; + } + + rcv_buf = (char *)malloc(len); + if (!rcv_buf) + { + fprintf(stderr, "Failed to malloc rcv_buf for mclagdctl\n"); + goto mclagdctl_disconnect; + } + + /*read data*/ + ret = mclagdctl_sock_read(mclagdctl_sock_fd, rcv_buf, len); + if(ret <= 0) + { + fprintf(stderr, "Failed to read data from mclagd\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + reply = (struct mclagd_reply_hdr *)rcv_buf; + + if (reply->info_type != cmd_type->info_type) + { + fprintf(stderr, "Reply info type from mclagd error\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + if (reply->exec_result == EXEC_TYPE_NO_EXIST_SYS) + { + fprintf(stderr, "No exist sys in iccpd!\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + if (reply->exec_result == EXEC_TYPE_NO_EXIST_MCLAGID) + { + fprintf(stderr, "Mclag-id %d hasn't been configured in iccpd!\n", mclag_id); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + if (reply->exec_result == EXEC_TYPE_FAILED) + { + fprintf(stderr, "exec error in iccpd!\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + cmd_type->parse_msg((char *)(rcv_buf + sizeof(struct mclagd_reply_hdr)), len - sizeof(struct mclagd_reply_hdr)); + + ret = EXIT_SUCCESS; + +mclagdctl_disconnect: + mclagdctl_sock_close(); + + if (rcv_buf) + free(rcv_buf); + + return ret; +} + diff --git a/src/iccpd/src/mclagdctl/mclagdctl.h b/src/iccpd/src/mclagdctl/mclagdctl.h new file mode 100644 index 000000000000..4219bff4e588 --- /dev/null +++ b/src/iccpd/src/mclagdctl/mclagdctl.h @@ -0,0 +1,177 @@ +/* Copyright(c) 2016-2019 Nephos. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: Jim Jiang from nephos +*/ + +#define MCLAGDCTL_PARA1_LEN 16 +#define MCLAGDCTL_PARA2_LEN 32 +#define MCLAGDCTL_PARA3_LEN 64 +#define MCLAGDCTL_CMD_SIZE 4096 + +#define MCLAGDCTL_MAX_L_PORT_NANE 32 +#define MCLAGDCTL_INET_ADDR_LEN 32 +#define MCLAGDCTL_ETHER_ADDR_LEN 6 +#define MCLAGDCTL_PORT_MEMBER_BUF_LEN 512 + +typedef int (*call_enca_msg_fun)(char *msg, int mclag_id, int argc, char **argv); +typedef int (*call_parse_msg_fun)(char *msg, int data_len); + +enum MAC_TYPE_CTL { + MAC_TYPE_STATIC_CTL = 1, + MAC_TYPE_DYNAMIC_CTL = 2, +}; + +enum MAC_AGE_TYPE_CTL { + MAC_AGE_LOCAL_CTL = 1,/*MAC in local switch is ageout*/ + MAC_AGE_PEER_CTL = 2/*MAC in peer switch is ageout*/ +}; + +enum id_command_type +{ + ID_CMDTYPE_NONE = 0, + ID_CMDTYPE_D, + ID_CMDTYPE_D_S, + ID_CMDTYPE_D_A, + ID_CMDTYPE_D_P, + ID_CMDTYPE_D_P_L, + ID_CMDTYPE_D_P_P, +}; + +enum mclagdctl_notify_peer_type +{ + INFO_TYPE_NONE = 0, + INFO_TYPE_DUMP_STATE, + INFO_TYPE_DUMP_ARP, + INFO_TYPE_DUMP_MAC, + INFO_TYPE_DUMP_LOCAL_PORTLIST, + INFO_TYPE_DUMP_PEER_PORTLIST, + INFO_TYPE_FINISH, +}; + +struct mclagdctl_req_hdr +{ + int info_type; + int mclag_id; + char para1[MCLAGDCTL_PARA2_LEN]; + char para2[MCLAGDCTL_PARA2_LEN]; + char para3[MCLAGDCTL_PARA2_LEN]; +}; + +struct mclagd_reply_hdr +{ + int info_type; + int data_len; + int exec_result; +}; + +#define EXEC_TYPE_SUCCESS -1 +#define EXEC_TYPE_NO_EXIST_SYS -2 +#define EXEC_TYPE_NO_EXIST_MCLAGID -3 +#define EXEC_TYPE_FAILED -4 + +#define MCLAGD_REPLY_INFO_HDR (sizeof(struct mclagd_reply_hdr) + sizeof(int)) + +#define MCLAGDCTL_COMMAND_PARAM_MAX_CNT 8 +struct command_type +{ + enum id_command_type id; + enum id_command_type parent_id; + enum mclagdctl_notify_peer_type info_type; + char *name; + char *params[MCLAGDCTL_COMMAND_PARAM_MAX_CNT]; + call_enca_msg_fun enca_msg; + call_parse_msg_fun parse_msg; +}; + +struct mclagd_state +{ + int mclag_id; + int keepalive; + unsigned char local_ip[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char peer_ip[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char peer_link_if[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char peer_link_mac[MCLAGDCTL_ETHER_ADDR_LEN]; + int role; + unsigned char enabled_po[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; +}; + +struct mclagd_arp_msg +{ + unsigned char op_type; + unsigned char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; +}; + +struct mclagd_mac_msg +{ + unsigned char op_type;/*add or del*/ + unsigned char fdb_type;/*static or dynamic*/ + char mac_str[32]; + unsigned short vid; + /*Current if name that set in chip*/ + char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + /*if we set the mac to peer-link, origin_ifname store the + original if name that learned from chip*/ + char origin_ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char age_flag;/*local or peer is age?*/ +}; + +struct mclagd_local_if +{ + int ifindex; + unsigned char type[MCLAGDCTL_PARA1_LEN]; + unsigned char name[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; + unsigned char state[MCLAGDCTL_PARA1_LEN]; + unsigned char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char prefixlen; + + unsigned char l3_mode; + unsigned char is_peer_link; + unsigned char portchannel_member_buf[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; + int po_id; /* Port Channel ID */ + unsigned char po_active; + unsigned char mlacp_state[MCLAGDCTL_PARA1_LEN]; + unsigned char isolate_to_peer_link; + + unsigned char vlanlist[MCLAGDCTL_PARA3_LEN]; +}; + +struct mclagd_peer_if +{ + int ifindex; + unsigned char type[MCLAGDCTL_PARA1_LEN]; + unsigned char name[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; + unsigned char state[MCLAGDCTL_PARA1_LEN]; + int po_id; + unsigned char po_active; +}; + +extern int mclagdctl_enca_dump_state(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_state(char *msg, int data_len); +extern int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_arp(char *msg, int data_len); +extern int mclagdctl_enca_dump_mac(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_mac(char *msg, int data_len); +extern int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_local_portlist(char *msg, int data_len); +extern int mclagdctl_enca_dump_peer_portlist(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len); + diff --git a/src/iccpd/src/mclagdctl/mclagdctl.o b/src/iccpd/src/mclagdctl/mclagdctl.o new file mode 100644 index 0000000000000000000000000000000000000000..0920a0d45ab142eae6ef20d6c1b7bbdc1eea302b GIT binary patch literal 86776 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 Uf9w. +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include "../include/mlacp_tlv.h" +#include "../include/mlacp_sync_prepare.h" +#include "../include/mlacp_link_handler.h" +#include "../include/mlacp_sync_update.h" + +#include + +/***************************************** +* Define +* +* ***************************************/ +#define MLACP_MSG_QUEUE_REINIT(list) \ + {\ + struct Msg* msg = NULL;\ + while (!TAILQ_EMPTY(&(list))) {\ + msg = TAILQ_FIRST(&(list));\ + TAILQ_REMOVE(&(list), msg, tail);\ + free(msg->buf);\ + free(msg);\ + }\ + TAILQ_INIT(&(list));\ + } + +#define PIF_QUEUE_REINIT(list) \ + { \ + while (!LIST_EMPTY(&(list))) { \ + struct PeerInterface* peer_if = NULL;\ + peer_if = LIST_FIRST(&(list)); \ + LIST_REMOVE(peer_if, mlacp_next); \ + free(peer_if); \ + } \ + LIST_INIT(&(list)); \ + } + +#define LIF_QUEUE_REINIT(list) \ + { \ + while (!LIST_EMPTY(&(list))) { \ + struct LocalInterface* lif = NULL;\ + lif = LIST_FIRST(&(list)); \ + if (lif->type == IF_T_PORT_CHANNEL && lif->is_arp_accept) { \ + if ((set_sys_arp_accept_flag(lif->name, 0)) == 0) \ + lif->is_arp_accept = 0; \ + } \ + LIST_REMOVE(lif, mlacp_next); \ + } \ + LIST_INIT(&(list)); \ + } + +#define LIF_PURGE_QUEUE_REINIT(list) \ + { \ + while (!LIST_EMPTY(&(list))) { \ + struct LocalInterface* lif = NULL;\ + lif = LIST_FIRST(&(list)); \ + LIST_REMOVE(lif, mlacp_purge_next); \ + } \ + LIST_INIT(&(list)); \ + } + +/***************************************** +* Static Function +* +* ***************************************/ +static char *mlacp_state(struct CSM* csm) ; +static void mlacp_resync_arp(struct CSM* csm); +static void mlacp_resync_mac(struct CSM* csm); +/* Sync Sender APIs*/ +static void mlacp_sync_send_sysConf(struct CSM* csm); +static void mlacp_sync_send_aggConf(struct CSM* csm); +static void mlacp_sync_send_aggState(struct CSM* csm); +static void mlacp_sync_send_syncArpInfo(struct CSM* csm); +static void mlacp_sync_send_heartbeat(struct CSM* csm); +static void mlacp_sync_send_syncDoneData(struct CSM* csm); +/* Sync Reciever APIs*/ +static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portConf(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portPrio(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portState(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_syncReq(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg); + +/* Sync Handler*/ +static void mlacp_sync_send_nak_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_sender_handler(struct CSM* csm); +static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_send_all_info_handler(struct CSM* csm); + +/* Sync State Handler*/ +static void mlacp_stage_sync_send_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_stage_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg); + +/****************************************************************** +* Sync Sender APIs +* +*****************************************************************/ +static void mlacp_sync_send_sysConf(struct CSM* csm) +{ + int msg_len = 0; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_sys_config(csm, g_csm_buf, CSM_BUFFER_SIZE); + if(msg_len > 0) + iccp_csm_send(csm, g_csm_buf, msg_len); + else + ICCPD_LOG_WARN("mlacp_fsm", " Invalid sysconf packet."); + + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] SysConf, len=[%d]", msg_len);*/ + + return; +} + +static void mlacp_sync_send_aggConf(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if, 0); + iccp_csm_send(csm, g_csm_buf, msg_len); + local_if->port_config_sync = 0; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ + } + } + + return; +} + +static void mlacp_sync_send_aggState(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + local_if->changed = 0; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ + } + } + + return; +} + +static void mlacp_sync_send_syncMacInfo(struct CSM* csm) +{ + int msg_len = 0; + struct Msg* msg = NULL; + + while (!TAILQ_EMPTY(&(MLACP(csm).mac_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).mac_msg_list), msg, tail); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct MACMsg*)msg->buf); + iccp_csm_send(csm, g_csm_buf, msg_len); + free(msg->buf); + free(msg); + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] MacInfo,len=[%d]", msg_len);*/ + } + + return; +} + +static void mlacp_sync_send_syncArpInfo(struct CSM* csm) +{ + int msg_len = 0; + struct Msg* msg = NULL; + + while (!TAILQ_EMPTY(&(MLACP(csm).arp_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_arp_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct ARPMsg*)msg->buf); + iccp_csm_send(csm, g_csm_buf, msg_len); + free(msg->buf); + free(msg); + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] ArpInfo,len=[%d]", msg_len);*/ + } + + return; +} + +static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_port_channel_info(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + local_if->changed = 0; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ + } + } + + return; +} + +static void mlacp_sync_send_syncPeerLinkInfo(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + + if((sys = system_get_instance()) == NULL) + return; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + + return; +} + +static void mlacp_sync_send_heartbeat(struct CSM* csm) +{ + int msg_len = 0; + + if ((csm->heartbeat_send_time == 0) || + ((time(NULL) - csm->heartbeat_send_time) > 1)) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_heartbeat(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); + time(&csm->heartbeat_send_time); + } + + return; +} + +static void mlacp_sync_send_syncDoneData(struct CSM* csm) +{ + int msg_len = 0; + + /*Sync done & go to next stage*/ + MLACP(csm).wait_for_sync_data = 0; + memset(g_csm_buf, 0 , CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_sync_data_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE, 1); + iccp_csm_send(csm, g_csm_buf, msg_len); + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] SyncDone, len=[%d]", msg_len);*/ + + return; +} + +/****************************************************************** +* Sync Receiver APIs +* +*****************************************************************/ +static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg) +{ + mLACPSysConfigTLV* sysconf = NULL; + + sysconf = (mLACPSysConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); + + if(mlacp_fsm_update_system_conf(csm, sysconf)==-1) + { + /*NOTE: we just change the node ID local side without sending NAK msg*/ + ICCPD_LOG_DEBUG("mlacp_fsm", " Same Node ID = %d, send NAK",MLACP(csm).remote_system.node_id); + mlacp_sync_send_nak_handler(csm, msg); + } + + return; +} + +static void mlacp_sync_recv_portConf(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_portPrio(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_portState(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg) +{ + mLACPAggConfigTLV* portconf = NULL; + + portconf = (mLACPAggConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_Agg_conf(csm, portconf) == -1) + { + mlacp_sync_send_nak_handler(csm, msg); + } + + return; +} + +static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg) +{ + mLACPAggPortStateTLV* portstate = NULL; + + portstate = (mLACPAggPortStateTLV*) &(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_Aggport_state(csm, portstate) == -1) + { + mlacp_sync_send_nak_handler(csm, msg); + /*MLACP(csm).error_msg = "Receive a port state update on an non-existed port. It is suggest to check the environment and re-initialize mLACP again.";*/ + return; + } + + return; +} + +static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg) +{ + mLACPSyncDataTLV* syncdata = NULL; + + syncdata = (mLACPSyncDataTLV*)&(msg->buf[sizeof(ICCHdr)]); + if(syncdata->flags == 1) + { + /* Sync done*/ + MLACP(csm).wait_for_sync_data = 0; + } + + return; +} + +static void mlacp_sync_recv_syncReq(struct CSM* csm, struct Msg* msg) +{ + mLACPSyncReqTLV* mlacp_sync_req = NULL; + mlacp_sync_req = (mLACPSyncReqTLV*) &msg->buf[sizeof(ICCHdr)]; + MLACP(csm).sync_req_num = mlacp_sync_req->req_num; + + /* Reply the peer all sync info*/ + mlacp_sync_send_all_info_handler(csm); + + return; +} + +static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg) +{ + mLACPPortChannelInfoTLV* portconf = NULL; + + portconf = (mLACPPortChannelInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_port_channel_info(csm, portconf) == -1) + { + mlacp_sync_send_nak_handler(csm, msg); + } + + return; +} + +static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg) +{ + mLACPPeerLinkInfoTLV* peerlink = NULL; + + peerlink = (mLACPPeerLinkInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_peerlink_info( csm, peerlink); + + return; +} + +static void mlacp_sync_recv_macInfo(struct CSM* csm, struct Msg* msg) +{ + struct mLACPMACInfoTLV* mac_info = NULL; + + mac_info = (struct mLACPMACInfoTLV *) &(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_mac_info_from_peer(csm, mac_info); + + return; +} + +static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg) +{ + struct mLACPARPInfoTLV* arp_info = NULL; + + arp_info = (struct mLACPARPInfoTLV *) &(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_arp_info(csm, arp_info); + + return; +} + +static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_heartbeat(struct CSM* csm, struct Msg* msg) +{ + struct mLACPHeartbeatTLV *tlv = NULL; + + tlv = (struct mLACPHeartbeatTLV *)(&msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_heartbeat(csm, tlv); + + return; +} + +/***************************************** +* MLACP Init +* +* ***************************************/ +void mlacp_init(struct CSM* csm, int all) +{ + if(csm == NULL) + return; + + MLACP(csm).sync_req_num = -1; + MLACP(csm).need_to_sync = 0; + MLACP(csm).error_msg = NULL; + + MLACP(csm).current_state = MLACP_STATE_INIT; + memset(MLACP(csm).remote_system.system_id, 0, ETHER_ADDR_LEN); + + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); + PIF_QUEUE_REINIT(MLACP(csm).pif_list); + LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list); + + if (all != 0) + { + /* if no clean all, keep the arp info & local interface info for next connection*/ + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list); + LIF_QUEUE_REINIT(MLACP(csm).lif_list); + + MLACP(csm).node_id = MLACP_SYSCONF_NODEID_MSB_MASK; + MLACP(csm).node_id |= (((inet_addr(csm->sender_ip) >> 24) << 4) & MLACP_SYSCONF_NODEID_NODEID_MASK); + MLACP(csm).node_id |= rand() % MLACP_SYSCONF_NODEID_FREE_MASK; + } + + return; +} + +/***************************************** +* MLACP finalize +* +* ***************************************/ +void mlacp_finalize(struct CSM* csm) +{ + if (csm == NULL) + return; + + /* msg destroy*/ + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list); + + /* remove lif & lif-purge queue */ + LIF_QUEUE_REINIT(MLACP(csm).lif_list); + LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list); + /* remove & destroy pif queue */ + PIF_QUEUE_REINIT(MLACP(csm).pif_list); + + return; +} + +/***************************************** +* MLACP FSM Transit +* +* ***************************************/ +void mlacp_fsm_transit(struct CSM* csm) +{ + struct System* sys = NULL; + struct Msg* msg = NULL; + static MLACP_APP_STATE_E prev_state = MLACP_SYNC_SYSCONF; + ICCHdr* icc_hdr = NULL; + ICCParameter* icc_param = NULL; + int have_msg=1; + + if (csm == NULL) + return; + if((sys = system_get_instance()) == NULL) + return; + + /* torn down event */ + if (csm->sock_fd <= 0 || csm->app_csm.current_state != APP_OPERATIONAL) + { + /* drop all legacy mlacp msg*/ + if (MLACP(csm).current_state != MLACP_STATE_INIT) + { + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); + MLACP(csm).current_state = MLACP_STATE_INIT; + } + return; + } + + /*Update port isolate after 3 seconds*/ + if(csm->isolate_update_time != 0 && (time(NULL) - csm->isolate_update_time) >= 3) + { + update_peerlink_isolate_from_all_csm_lif(csm); + csm->isolate_update_time = 0; + } + + mlacp_sync_send_heartbeat(csm); + + /* Dequeue msg if any*/ + while (have_msg) + { + if (MLACP(csm).current_state != MLACP_STATE_INIT) + { + /* Handler NAK First*/ + msg = mlacp_dequeue_msg(csm); + if (msg!=NULL) + { + have_msg=1; + icc_hdr = (ICCHdr*) msg->buf; + icc_param = (ICCParameter*) &msg->buf[sizeof(ICCHdr)]; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " SYNC: Message Type = %X, TLV=%s, Len=%d", icc_hdr->ldp_hdr.msg_type, get_tlv_type_string(icc_param->type), msg->len);*/ + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION && icc_param->type == TLV_T_NAK) + { + mlacp_sync_recv_nak_handler(csm, msg); + free(msg->buf); + free(msg); + continue; + } + } + else + { + have_msg=0; + } + } + + if (prev_state != MLACP(csm).current_state) + { + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + mlacp_peerlink_conn_handler(csm); + prev_state = MLACP(csm).current_state; + } + + /* Sync State */ + if (MLACP(csm).current_state == MLACP_STATE_INIT) + { + MLACP(csm).wait_for_sync_data = 0; + MLACP(csm).current_state = MLACP_STATE_STAGE1; + mlacp_resync_mac(csm); + mlacp_resync_arp(csm); + } + + switch (MLACP(csm).current_state) + { + case MLACP_STATE_INIT: + case MLACP_STATE_ERROR: + /* should not be here*/ + break; + + case MLACP_STATE_STAGE1: + case MLACP_STATE_STAGE2: + mlacp_stage_handler(csm, msg); + break; + + case MLACP_STATE_EXCHANGE: + mlacp_exchange_handler(csm, msg); + break; + } + + /*ICCPD_LOG_DEBUG("mlacp_fsm", " Next State = %s", mlacp_state(csm));*/ + if (msg) + { + free(msg->buf); + free(msg); + } + } +} + +/* Helper function for dumping application state machine */ +static char* mlacp_state(struct CSM* csm) +{ + if (csm == NULL ) + return "MLACP_NULL"; + + switch (MLACP(csm).current_state) + { + case MLACP_STATE_INIT: + return "MLACP_STATE_INIT"; + case MLACP_STATE_STAGE1: + return "MLACP_STATE_STAGE1"; + case MLACP_STATE_STAGE2: + return "MLACP_STATE_STAGE2"; + case MLACP_STATE_EXCHANGE: + return "MLACP_STATE_EXCHANGE"; + case MLACP_STATE_ERROR: + return "MLACP_STATE_ERROR"; + } + + return "MLACP_UNKNOWN"; +} + +/* Add received message into message list */ +void mlacp_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + if (csm == NULL ) + { + if (msg != NULL ) + free(msg); + return; + } + + if (msg == NULL ) + return; + + #if 0 + icc_hdr = (ICCHdr*) msg->buf; + icc_param = (ICCParameter*) &msg->buf[sizeof(ICCHdr)]; + ICCPD_LOG_DEBUG("mlacp_fsm", " mLACP enqueue: tlv = 0x%04x", icc_param->type); + #endif + + TAILQ_INSERT_TAIL(&(MLACP(csm).mlacp_msg_list), msg, tail); + + return; +} + +/* Get received message from message list */ +struct Msg* mlacp_dequeue_msg(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (!TAILQ_EMPTY(&(MLACP(csm).mlacp_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).mlacp_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).mlacp_msg_list), msg, tail); + } + + return msg; +} + +/****************************************** +* When peerlink ready, prepare the MACMsg +* +******************************************/ +static void mlacp_resync_mac(struct CSM* csm) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + struct Msg *msg_send = NULL; + + /* recover MAC info sync from peer*/ + if(!TAILQ_EMPTY(&(MLACP(csm).mac_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*) msg->buf; + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } +} + +/****************************************** +* When peerlink ready, prepare the ARPMsg +* +******************************************/ +static void mlacp_resync_arp(struct CSM* csm) +{ + struct Msg* msg = NULL; + struct ARPMsg* arp_msg = NULL; + struct Msg *msg_send = NULL; + + /* recover ARP info sync from peer*/ + if(!TAILQ_EMPTY(&(MLACP(csm).arp_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + arp_msg->op_type = ARP_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + } + } + } +} + +/***************************************** +* NAK handler +* +* ***************************************/ +static void mlacp_sync_send_nak_handler(struct CSM* csm, struct Msg* msg) +{ + int msg_len; + ICCHdr* icc_hdr = NULL; + + icc_hdr = (ICCHdr*) msg->buf; + + ICCPD_LOG_WARN("mlacp_fsm", " ### Send NAK ###"); + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + csm->app_csm.invalid_msg_id = icc_hdr->ldp_hdr.msg_id; + msg_len = app_csm_prepare_nak_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); +} + +static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg) +{ + NAKTLV* naktlv = NULL; + uint16_t tlvType = -1; + int i; + + ICCPD_LOG_WARN("mlacp_fsm", " ### Receive NAK ###"); + + /* Dequeuq NAK*/ + naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; + + /* Check NAK Type*/ + for(i=0; irejected_msg_id == csm->msg_log.msg[i].msg_id) + { + tlvType = csm->msg_log.msg[i].tlv; + break; + } + } + + if(tlvType) + { + switch (tlvType) + { + case TLV_T_MLACP_SYSTEM_CONFIG: + MLACP(csm).node_id--; + MLACP(csm).system_config_changed=1; + ICCPD_LOG_WARN("mlacp_fsm", " [%X] change NodeID as %d", tlvType&0x00FF, MLACP(csm).node_id); + break; + + default: + ICCPD_LOG_WARN("mlacp_fsm", " [%X]", tlvType&0x00FF); + MLACP(csm).need_to_sync = 1; + break; + } + } + else + { + ICCPD_LOG_WARN("mlacp_fsm", " Unknow NAK"); + MLACP(csm).need_to_sync = 1; + } + + return; +} + +/***************************************** +* MLACP sync receiver +* +* ***************************************/ +static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg) +{ + ICCParameter *icc_param; + + /* No receive message...*/ + if (!csm || !msg) + return; + + icc_param = (ICCParameter*)&(msg->buf[sizeof(ICCHdr)]); + + /*fprintf(stderr, " Recv Type [%d]\n", icc_param->type);*/ + switch(icc_param->type) + { + case TLV_T_MLACP_SYSTEM_CONFIG: + mlacp_sync_recv_sysConf(csm, msg); + break; + + case TLV_T_MLACP_PORT_CONFIG: + mlacp_sync_recv_portConf(csm, msg); + break; + + case TLV_T_MLACP_PORT_PRIORITY: + mlacp_sync_recv_portPrio(csm, msg); + break; + + case TLV_T_MLACP_PORT_STATE: + mlacp_sync_recv_portState(csm, msg); + break; + + case TLV_T_MLACP_AGGREGATOR_CONFIG: + /* The following line will be uncommented when Aggregator related structures are supported. */ + mlacp_sync_recv_aggConf(csm, msg); + break; + + case TLV_T_MLACP_AGGREGATOR_STATE: + mlacp_sync_recv_aggState(csm, msg); + break; + + case TLV_T_MLACP_SYNC_DATA: + mlacp_sync_recv_syncData(csm, msg); + break; + + case TLV_T_MLACP_SYNC_REQUEST: + mlacp_sync_recv_syncReq(csm, msg); + break; + + case TLV_T_MLACP_PORT_CHANNEL_INFO: + mlacp_sync_recv_portChanInfo(csm, msg); + break; + + case TLV_T_MLACP_PEERLINK_INFO: + mlacp_sync_recv_peerLlinkInfo(csm, msg); + break; + + case TLV_T_MLACP_MAC_INFO: + mlacp_sync_recv_macInfo(csm, msg); + break; + + case TLV_T_MLACP_ARP_INFO: + mlacp_sync_recv_arpInfo(csm, msg); + break; + + case TLV_T_MLACP_STP_INFO: + mlacp_sync_recv_stpInfo(csm, msg); + break; + case TLV_T_MLACP_HEARTBEAT: + mlacp_sync_recv_heartbeat(csm, msg); + break; + } + + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [Sync Recv] %s... DONE", get_tlv_type_string(icc_param->type));*/ + + return; +} + +/***************************************** +* MLACP sync sender +* +* ***************************************/ +static void mlacp_sync_sender_handler(struct CSM* csm) +{ + switch(MLACP(csm).sync_state) + { + case MLACP_SYNC_SYSCONF: + mlacp_sync_send_sysConf(csm); + break; + + case MLACP_SYNC_AGGCONF: + /* Do nothing due to no support in this version. */ + mlacp_sync_send_aggConf(csm); + break; + + case MLACP_SYNC_AGGSTATE: + /* Do nothing due to no support in this version. */ + mlacp_sync_send_aggState(csm); + break; + + case MLACP_SYNC_AGGINFO: + mlacp_sync_send_syncPortChannelInfo(csm); + break; + + case MLACP_SYNC_PEERLINKINFO: + mlacp_sync_send_syncPeerLinkInfo(csm); + break; + + case MLACP_SYNC_ARP_INFO: + mlacp_sync_send_syncArpInfo(csm); + break; + + case MLACP_SYNC_DONE: + mlacp_sync_send_syncDoneData(csm); + break; + + default: + break; + }; + + return; +} + +static void mlacp_sync_send_all_info_handler(struct CSM* csm) +{ + size_t len = 0; + + /* Prepare for sync start reply*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_sync_data_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE, 0); + iccp_csm_send(csm, g_csm_buf, len); + + MLACP(csm).sync_state = MLACP_SYNC_SYSCONF; + while(1) + { + mlacp_sync_sender_handler(csm); + if(MLACP(csm).sync_state != MLACP_SYNC_DONE) + { + MLACP(csm).sync_state++; + } + else + { + /*Next stage*/ + MLACP(csm).wait_for_sync_data = 0; + MLACP(csm).current_state++; + break; + } + } + + return; +} + +static void mlacp_stage_sync_send_handler(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + ICCParameter* icc_param = NULL; + mLACPSyncReqTLV* mlacp_sync_req = NULL; + + if (MLACP(csm).wait_for_sync_data == 0) + { + /* Waiting the peer sync request*/ + if(msg){ + icc_hdr = (ICCHdr*) msg->buf; + icc_param = (ICCParameter*) &msg->buf[sizeof(ICCHdr)]; + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA && icc_param->type == TLV_T_MLACP_SYNC_REQUEST) + { + mlacp_sync_req = (mLACPSyncReqTLV*) &msg->buf[sizeof(ICCHdr)]; + MLACP(csm).wait_for_sync_data = 1; + MLACP(csm).sync_req_num = mlacp_sync_req->req_num; + + /* Reply the peer all sync info*/ + mlacp_sync_send_all_info_handler(csm); + } + } + } + + return; +} + +static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg) +{ + int msg_len=0; + /* Socket server send sync request first*/ + if (MLACP(csm).wait_for_sync_data == 0) + { + // Send out the request for ALL + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_sync_request_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); + MLACP(csm).wait_for_sync_data = 1; + } + else + { + mlacp_sync_receiver_handler(csm, msg); + if(MLACP(csm).wait_for_sync_data == 0) + { + MLACP(csm).current_state++; + } + } + + return; +} + +static void mlacp_stage_handler(struct CSM* csm, struct Msg* msg) +{ + if(MLACP(csm).current_state==MLACP_STATE_STAGE1) + { + /*Stage 1, role active send info first*/ + if (csm->role_type == STP_ROLE_ACTIVE) + mlacp_stage_sync_send_handler(csm, msg); + else + mlacp_stage_sync_request_handler(csm, msg); + } + else + { + /*Stage 2, role standby send info*/ + if (csm->role_type == STP_ROLE_ACTIVE) + mlacp_stage_sync_request_handler(csm, msg); + else + mlacp_stage_sync_send_handler(csm, msg); + } + + return; +} + +static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) +{ + int len; + struct System* sys = NULL; + struct LocalInterface* lif = NULL, *lif_purge = NULL; + + ICCHdr* icc_hdr = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + /* update system id*/ + update_system_id(csm); + + /* Any msg?*/ + if (msg) + { + icc_hdr = (ICCHdr*) msg->buf; + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + /* Process receive APP info*/ + mlacp_sync_receiver_handler(csm, msg); + } + } + + if (MLACP(csm).need_to_sync != 0) + { + /* Send out the request for ALL info*/ + MLACP(csm).need_to_sync = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_sync_request_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + } + + /* Send system config*/ + if (MLACP(csm).system_config_changed != 0) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_sys_config(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); + iccp_csm_send(csm, g_csm_buf, len); + + MLACP(csm).system_config_changed = 0; + } + + /* Send mlag purge lif*/ + LIST_FOREACH(lif_purge, &(MLACP(csm).lif_purge_list), mlacp_purge_next) + { + /* Purge info*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif_purge,1); + iccp_csm_send(csm, g_csm_buf, len); + /* Destroy old interface*/ + if (lif_purge != NULL) + LIST_REMOVE(lif_purge, mlacp_purge_next); + } + + /* Send mlag lif*/ + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT_CHANNEL && lif->port_config_sync) + { + /* Send port channel information*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif,0); + iccp_csm_send(csm, g_csm_buf, len); + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_port_channel_info(csm, g_csm_buf, CSM_BUFFER_SIZE, lif); + iccp_csm_send(csm, g_csm_buf, len); + + lif->port_config_sync = 0; + } + + /*send if portchannel state change */ + if (lif->type == IF_T_PORT_CHANNEL && lif->changed) + { + /* Send port channel state information*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, lif); + iccp_csm_send(csm, g_csm_buf, len); + lif->changed = 0; + } + } + + /* Send MAC info if any*/ + mlacp_sync_send_syncMacInfo(csm); + + /* Send ARP info if any*/ + mlacp_sync_send_syncArpInfo(csm); + + return; +} \ No newline at end of file diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c new file mode 100644 index 000000000000..e18743b18a0d --- /dev/null +++ b/src/iccpd/src/mlacp_link_handler.c @@ -0,0 +1,1789 @@ +/* +* mlacp_link_handler.c +* mLACP link handler +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_tlv.h" + +#include "../include/mlacp_link_handler.h" + +#include "mclagdctl/mclagdctl.h" + +/***************************************** +* Enum +* +* ***************************************/ +typedef enum route_manipulate_type { + ROUTE_NONE, + ROUTE_ADD, + ROUTE_DEL +} ROUTE_MANIPULATE_TYPE_E; + + +/***************************************** +* Global +* +* ***************************************/ +char g_ipv4_str[INET_ADDRSTRLEN]; + +static int arp_set_handler(struct CSM* csm, + struct LocalInterface* lif, + int add) +{ + struct Msg* msg = NULL; + struct ARPMsg* arp_msg = NULL; + char mac_str[18] = ""; + + if (!csm || !lif) + return 0; + + if (add) + goto add_arp; + else + goto del_arp; + + /* Process Add */ +add_arp: + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return 0; + + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + mac_str[0] = '\0'; + arp_msg = (struct ARPMsg*) msg->buf; + + /* only process add*/ + if (arp_msg->op_type == ARP_SYNC_DEL) + continue; + + /* find the ARP for lif_list*/ + if (strcmp(lif->name, arp_msg->ifname) != 0) + continue; + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], + arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); + + mlacp_fsm_arp_set(arp_msg->ifname, arp_msg->ipv4_addr, mac_str); + ICCPD_LOG_DEBUG(__FUNCTION__, "Add dynamic ARP to kernel [%s]", + show_ip_str(arp_msg->ipv4_addr)); + } + goto done; + +del_arp: + /* Process Del */ + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + + /* find the ARP for lif_list*/ + if (strcmp(lif->name, arp_msg->ifname) != 0) + continue; + + /* don't process del*/ + if (arp_msg->op_type == ARP_SYNC_DEL) + continue; + + mlacp_fsm_arp_del(arp_msg->ifname, arp_msg->ipv4_addr); + /* link broken, del all static arp on the lif*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Del dynamic ARP [%s]", + show_ip_str(arp_msg->ipv4_addr)); + } + +done: + return 0; +} + +/***************************************** +* Port-Channel Status Handler +* +****************************************/ +static void set_route_by_linux_route(struct CSM* csm, + struct LocalInterface *local_if, + int is_add) +{ + /* TODO Need to remove this function + when set static route with zebra works fine*/ + + char ipv4_dest_str[INET_ADDRSTRLEN]; + char syscmd[128]; + char *ptr; + int ret = 0; + + /* enable kernel forwarding support*/ + system("echo 1 > /proc/sys/net/ipv4/ip_forward"); + + if(!csm || !local_if) + return; + + sprintf(ipv4_dest_str, "%s", show_ip_str(htonl(local_if->ipv4_addr))); + ptr=strrchr(ipv4_dest_str, '.');strcpy(ptr, ".0\0"); + +#if 1 + /* set gw route*/ + /*sprintf(syscmd, "ip route %s %s/%d proto static metric 200 nexthop via %s > /dev/null 2>&1",*/ + sprintf(syscmd, "ip route %s %s/%d metric 200 nexthop via %s > /dev/null 2>&1", + (is_add)?"add":"del", ipv4_dest_str, local_if->prefixlen, + csm->peer_ip); +#else + // set interface route + sprintf(syscmd, "route %s -net %s/%d %s > /dev/null 2>&1", + (is_add)?"add":"del", ipv4_dest_str, local_if->prefixlen, + local_if->name); +#endif + + ret = system(syscmd); + ICCPD_LOG_DEBUG(__FUNCTION__, " %s ret = %d", syscmd,ret); + + return; +} + +static void update_vlan_if_info(struct CSM *csm, + struct LocalInterface *local_if, + struct LocalInterface *vlan_if, + int po_state) +{ + if (!csm || !local_if || !vlan_if) + return; + + vlan_if->mlacp_state = MLACP(csm).current_state; + + return; +} + +static void update_l3_if_info(struct CSM *csm, + struct LocalInterface *local_if, + struct LocalInterface *l3_if, + int po_state) +{ + if (!csm || !l3_if) + return; + + l3_if->mlacp_state = MLACP(csm).current_state; + + return; +} + +static void update_po_if_info(struct CSM *csm, + struct LocalInterface *local_if, + int po_state) +{ + if (!csm || !local_if) + return; + + /* update local po info*/ + if(local_if->po_active != po_state) + { + local_if->changed = 1; + local_if->po_active = (po_state!=0); + /*printf("update po [%s=%d]\n",local_if->name, local_if->po_active);*/ + } + local_if->mlacp_state = MLACP(csm).current_state; + + return; +} + +static void set_l3_itf_state(struct CSM *csm, + struct LocalInterface *set_l3_local_if, + ROUTE_MANIPULATE_TYPE_E route_type) +{ + if (!csm || !set_l3_local_if) + return; + + if (set_l3_local_if && (route_type != ROUTE_NONE)) + { + /*set_default_route(csm);*/ + + ICCPD_LOG_DEBUG(__FUNCTION__, " route set Interface = %s route type = %d route = %s nexthop via = %s ", + set_l3_local_if->name, route_type, show_ip_str(set_l3_local_if->ipv4_addr), csm->peer_ip ); + + /* set static route*/ + if(route_type == ROUTE_ADD) + { + /*set_route_by_linux_route(csm, set_l3_local_if, 1);*/ /*add static route by linux route tool*/ + arp_set_handler(csm, set_l3_local_if, 0); /* del arp*/ + } + else if(route_type == ROUTE_DEL) + { + /*set_route_by_linux_route(csm, set_l3_local_if, 0);*/ /*del static route by linux route tool*/ + arp_set_handler(csm, set_l3_local_if, 1); /* add arp*/ + } + } + + return; +} + +static int peer_po_is_alive(struct CSM *csm, int po_ifindex) +{ + struct PeerInterface *pif = NULL; + int pif_active = 0; + + if (!csm) + return 0; + + LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) + { + if(pif->type != IF_T_PORT_CHANNEL) + continue; + if(pif->po_id!= po_ifindex) + continue; + + if(pif->po_active) + pif_active = 1; /*pif alive*/ + break; + } + + return pif_active; +} + +static void mlacp_clean_fdb (void) +{ + struct IccpSyncdHDr * msg_hdr; + char msg_buf[4096] = {0}; + int msg_len; + + struct System *sys; + + sys = system_get_instance(); + if(sys == NULL) + return; + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_FLUSH_FDB; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + if(sys->sync_fd) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + ICCPD_LOG_DEBUG(__FUNCTION__, "notify mclagsyncd clear fdb"); + + return; +} + +void set_peerlink_mlag_port_learn (struct LocalInterface *lif, int enable) +{ + struct IccpSyncdHDr * msg_hdr; + mclag_sub_option_hdr_t * sub_msg; + char msg_buf[4096]; + int msg_len; + struct System *sys; + + sys = system_get_instance(); + if(sys == NULL) + return; + + if (!lif) + return; + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE; + + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + sub_msg =(mclag_sub_option_hdr_t*) &msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE; + + if(enable) + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE; + + msg_len = strlen(lif->name); + memcpy(sub_msg->data, lif->name, msg_len); + + sub_msg->op_len = msg_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + ICCPD_LOG_DEBUG(__FUNCTION__, " send port-learn msg to sync for %s , member %s", + lif->name, sub_msg->data); + + /*send msg*/ + if(sys->sync_fd) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + +static void set_peerlink_mlag_port_kernel_forward ( + struct CSM *csm, + struct LocalInterface *lif, + int enable) +{ + struct VLAN_ID* vlan_id = NULL; + + if (!csm || !csm->peer_link_if || !lif) + return; + + char cmd[256] = {0}; + + sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP", + "-D", csm->peer_link_if->name, lif->name); + ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s",cmd ); + system(cmd); + + sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP", + (enable)?"-A":"-D", csm->peer_link_if->name, lif->name); + ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s",cmd ); + system(cmd); + + return; +} + +void update_peerlink_isolate_from_all_csm_lif ( + struct CSM* csm) +{ + struct LocalInterface *lif = NULL; + struct IccpSyncdHDr * msg_hdr; + mclag_sub_option_hdr_t * sub_msg; + char msg_buf[4096]; + struct System *sys; + + char mlag_po_buf[512]; + int src_len = 0,dst_len =0; + char src_buf[2048]; + + sys = system_get_instance(); + if(sys == NULL) + return; + + if (!csm || !csm->peer_link_if) return; + + memset(msg_buf,0,4095); + memset(mlag_po_buf,0, 511); + memset(src_buf,0,2047); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_PORT_ISOLATE; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + /*sub msg src*/ + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC; + + if(csm->peer_link_if->type == IF_T_PORT) + { + src_len= strlen(csm->peer_link_if->name); + memcpy(sub_msg->data, csm->peer_link_if->name, src_len); + } + else + { + src_len= strlen(csm->peer_link_if->portchannel_member_buf); + memcpy(sub_msg->data, csm->peer_link_if->portchannel_member_buf, src_len); + } + sub_msg->op_len = src_len; + + /*sub msg dst */ + msg_hdr->len += sub_msg->op_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_ISOLATE_DST; + + /*traverse all portchannel member port and send msg to syncd */ + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if(lif->type !=IF_T_PORT_CHANNEL) + continue; + + /* check pif port state and lif pochannel state */ + if(lif->isolate_to_peer_link == 1) + { + /* need to isolate port, get it's member name */ + if(strlen(mlag_po_buf) != 0) + dst_len += snprintf(mlag_po_buf+dst_len, sizeof(mlag_po_buf)-dst_len, "%s",","); + + dst_len += snprintf(mlag_po_buf+dst_len, sizeof(mlag_po_buf)-dst_len, "%s", lif->portchannel_member_buf); + } + } + + sub_msg->op_len = dst_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + if(dst_len) + { + memcpy(sub_msg->data, mlag_po_buf, dst_len); + ICCPD_LOG_DEBUG(__FUNCTION__, "isolate dst %s, data %s, len %d",mlag_po_buf, sub_msg->data, dst_len); + } + + /*send msg*/ + if(sys->sync_fd) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + +static void set_peerlink_mlag_port_isolate ( + struct CSM *csm, + struct LocalInterface *lif, + int enable) +{ + if (!csm || !csm->peer_link_if || !lif) + return; + + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + lif->isolate_to_peer_link = enable; + + /*update_peerlink_isolate_from_all_csm_lif(csm);*/ + csm->isolate_update_time = time(NULL); + + /* Kernel also needs to block traffic from peerlink to mlag-port*/ + set_peerlink_mlag_port_kernel_forward(csm, lif, enable); + + return; +} + +void peerlink_port_isolate_cleanup(struct CSM* csm) +{ + struct LocalInterface *local_if=NULL; + struct VLAN_ID *vlan=NULL; + + if (!csm) + return; + + /* Clean all port block*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if(local_if->type == IF_T_PORT_CHANNEL) + { + set_peerlink_mlag_port_isolate(csm, local_if, 0); + } + } + + return; +} + +void update_peerlink_isolate_from_pif ( + struct CSM *csm, + struct PeerInterface *pif, + int pif_po_state, + int new_create) +{ + struct LocalInterface *lif = NULL; + int lif_po_state = 1; + + if(!csm || !csm->peer_link_if || !pif) return; + if(new_create == 0 && pif_po_state == pif->po_active) return; + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + /* peer link changed*/ + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if(strcmp(lif->name, pif->name)!=0) + continue; + + lif_po_state = lif->po_active; + break; + } + + if (!lif) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "can't find lif"); + return; + } + + ICCPD_LOG_DEBUG(__FUNCTION__, " from peer %s local(%s) / peer(%s)", + lif->name, + (lif_po_state) ? "up" : "down", + (pif_po_state) ? "up" : "down"); + + if (lif_po_state == 1) + { + if (pif_po_state == 1) + { + /* both peer-pair link up, enable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, " Enable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 1); + } + else + { + /* local link up, and peer link changes to down, disable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Disable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 0); + } + } + else + { + ;/* local link down, do nothing*/ + } + + return; +} + +static void update_peerlink_isolate_from_lif ( + struct CSM* csm, + struct LocalInterface* lif, + int lif_po_state) +{ + struct PeerInterface *pif = NULL; + int pif_po_state = 1; + + if (!csm || !csm->peer_link_if || !lif) return; + /*if (lif_po_state == lif->po_active) return;*/ + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + /* local link changed*/ + LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) + { + if (strcmp(pif->name, lif->name)!=0) + continue; + + pif_po_state = pif->po_active; + break; + } + + ICCPD_LOG_DEBUG(__FUNCTION__, " from local %s local(%s) / peer(%s)", + lif->name,(lif_po_state) ? "up" : "down", (pif_po_state) ? "up" : "down"); + + if (lif_po_state == 1) + { + if (pif_po_state == 1) + { + /* both peer-pair link up, enable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Enable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 1); + } + else + { + /* peer link down, local link changes to up, disable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, " Disable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 0); + } + } + else + { + ;/* local link down, do nothing*/ + } + + return; +} + +static void update_l2_po_state(struct CSM *csm, + struct LocalInterface *lif, + int po_state) +{ + ROUTE_MANIPULATE_TYPE_E route_type=ROUTE_NONE; + struct VLAN_ID *vlan=NULL; + struct LocalInterface *set_l3_vlan_if=NULL; + + if (!csm || !lif) + return; + + /*L2 po*/ + /*if (po_state != lif->po_active && po_state == 0) + { + mlacp_clean_fdb(); + }*/ + + /*Is there any L3 vlan over L2 po?*/ + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + route_type = ROUTE_NONE; + + if(!vlan->vlan_itf) + continue; + + /* If the po is under a vlan, update vlan state first*/ + update_vlan_if_info(csm, lif, vlan->vlan_itf, po_state); + + if(!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + /*NOTE + * assume only one mlag per vlan + * need to add rules for per mlag per vlan later (arp list?) + */ + set_l3_vlan_if = vlan->vlan_itf; + if (po_state != lif->po_active + || MLACP(csm).current_state != set_l3_vlan_if->mlacp_state) + { + if(po_state==1) + { + route_type = ROUTE_DEL; + } + else if(po_state == 0 + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + if (peer_po_is_alive(csm, lif->ifindex) == 1) + route_type = ROUTE_ADD; + } + } + + /*update_po_arp_list(csm, set_l3_vlan_if);*/ + set_l3_itf_state(csm, set_l3_vlan_if, route_type); + update_l3_if_info(csm, lif, set_l3_vlan_if, po_state); + } + + return; +} + +static void update_l3_po_state(struct CSM *csm, + struct LocalInterface *lif, + int po_state) +{ + ROUTE_MANIPULATE_TYPE_E route_type=ROUTE_NONE; + struct LocalInterface *set_l3_lif=NULL; + /*L3 po*/ + set_l3_lif = lif; + + if (!csm || !lif) + return; + + if(po_state != lif->po_active + && po_state == 1) + { + /* po alive, clean static route & recover the ARP*/ + route_type = ROUTE_DEL; + } + else if(po_state != lif->po_active + && po_state == 0 + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /* po is not alive & peer-link alive, set static route*/ + if (peer_po_is_alive(csm, lif->po_id) == 1) + route_type = ROUTE_ADD; + } + else if(MLACP(csm).current_state != lif->mlacp_state + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE + && po_state == 0) + { + /* when peer-pair link ready, set static route for broken po link*/ + if (peer_po_is_alive(csm, lif->po_id) == 1) + route_type = ROUTE_ADD; + } + + /*update_po_arp_list(csm, set_l3_lif);*/ + set_l3_itf_state(csm, set_l3_lif, route_type); + update_l3_if_info(csm, lif, set_l3_lif, po_state); + + return; +} + +int is_local_vlan_on(struct VLAN_ID* vlan_id_list) +{ + if(!vlan_id_list->vlan_itf) + return 0; + + return 1; +} + +void syn_arp_info_to_peer(struct CSM *csm, struct LocalInterface *local_if) +{ + struct Msg *msg = NULL; + struct ARPMsg *arp_msg = NULL, *arp_info = NULL; + struct Msg *msg_send = NULL; + + if(!csm || !local_if) + return; + + if(!TAILQ_EMPTY(&(MLACP(csm).arp_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_info = (struct ARPMsg*) msg->buf; + + if(strcmp(arp_info->ifname, local_if->name)!=0) + continue; + + arp_msg = (struct ARPMsg*) msg->buf; + arp_msg->op_type = ARP_SYNC_ADD; + + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG( __FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + } + + return; +} + +void update_stp_peer_link(struct CSM *csm, + struct PeerInterface *pif, + int po_state, int new_create) +{ + struct LocalInterface *lif=NULL; + struct VLAN_ID *vlan=NULL; + + if(!csm || !pif) + return; + if(new_create == 0 && po_state == pif->po_active) + return; + + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if(strcmp(lif->name, pif->name)!=0) + continue; + + /* update lif route if pif link status changes */ + if (local_if_is_l3_mode(lif)) + { + if (po_state == 1 && lif->po_active == 0) + set_l3_itf_state(csm, lif, ROUTE_ADD); + else if (po_state == 0 && lif->po_active == 0) + set_l3_itf_state(csm, lif, ROUTE_DEL); + + /*If pif change to active, and local is also active, syn arp to peer*/ + if (po_state == 1 && lif->po_active == 1) + { + syn_arp_info_to_peer(csm, lif); + } + } + else + { + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if(!is_local_vlan_on(vlan)) + continue; + if(!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + /*NOTE + * assume only one mlag per bridge + * need to add rules for per mlag per bridge later (arp list?) + */ + if (po_state == 1 && lif->po_active == 0) + set_l3_itf_state(csm, vlan->vlan_itf, ROUTE_ADD); + else if (po_state == 0 && lif->po_active == 0) + set_l3_itf_state(csm, vlan->vlan_itf, ROUTE_DEL); + + /*If pif change to active, and local is also active, syn arp to peer*/ + if (po_state == 1 && lif->po_active == 1) + { + syn_arp_info_to_peer(csm, vlan->vlan_itf); + } + } + } + + break; + } + + return; +} + +void iccp_get_fdb_change_from_syncd( void) +{ + struct IccpSyncdHDr * msg_hdr; + char msg_buf[4096]; + struct System *sys; + + sys = system_get_instance(); + if(sys == NULL) + return; + + memset(msg_buf,0,4095); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_GET_FDB_CHANGES; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d write get fdb change msg ", + sys->sync_fd); + + /*send msg*/ + if(sys->sync_fd > 0) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + +void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg,uint8_t mac_type) +{ + struct IccpSyncdHDr * msg_hdr; + char msg_buf[4096]; + struct System *sys; + struct mclag_fdb_info * mac_info; + + sys = system_get_instance(); + if(sys == NULL) + return; + + memset(msg_buf,0,4095); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_SET_FDB; + + /*mac msg */ + mac_info = (struct mclag_fdb_info *)&msg_buf[sizeof(struct IccpSyncdHDr)]; + mac_info->vid = mac_msg->vid; + memcpy(mac_info->port_name,mac_msg->ifname,MAX_L_PORT_NAME); + memcpy(mac_info->mac ,mac_msg->mac_str,32); + mac_info->type = mac_type; + mac_info->op_type = mac_msg->op_type; + msg_hdr->len = sizeof(struct IccpSyncdHDr)+sizeof(struct mclag_fdb_info); + + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d write mac msg vid : %d ; ifname %s ; mac %s fdb type %d ; op type %d ", + sys->sync_fd,mac_info->vid,mac_info->port_name,mac_info->mac, mac_info->type,mac_info->op_type); + + /*send msg*/ + if(sys->sync_fd > 0 ) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + +void add_mac_to_chip(struct MACMsg* mac_msg, uint8_t mac_type) +{ + mac_msg->op_type = MAC_SYNC_ADD; + iccp_send_fdb_entry_to_syncd( mac_msg, mac_type); + + return; +} + +void del_mac_from_chip(struct MACMsg* mac_msg) +{ + mac_msg->op_type = MAC_SYNC_DEL; + iccp_send_fdb_entry_to_syncd( mac_msg, mac_msg->fdb_type); + + return; +} + +uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t set ) +{ + uint8_t new_age_flag = 0; + struct Msg *msg = NULL; + + new_age_flag = mac_msg->age_flag; + + if(set == 0)/*remove age flag*/ + { + if(new_age_flag & MAC_AGE_LOCAL) + { + new_age_flag &= ~MAC_AGE_LOCAL; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove local age flag: %d ifname %s, add %s vlan-id %d, age_flag %d", + new_age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + + /*send mac MAC_SYNC_ADD message to peer*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } + } + else/*set age flag*/ + { + if(!(new_age_flag & MAC_AGE_LOCAL)) + { + new_age_flag |= MAC_AGE_LOCAL; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Add local age flag: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + + /*send mac MAC_SYNC_DEL message to peer*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + mac_msg->op_type = MAC_SYNC_DEL; + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } + } + + return new_age_flag; +} + +/*Deal with mac add,del,move when portchannel up or down*/ +static void update_l2_mac_state(struct CSM *csm, + struct LocalInterface *lif, + int po_state) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + + if (!csm || !lif) + return; + + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*) msg->buf; + + /* find the MAC for this interface*/ + if (strcmp(lif->name, mac_msg->origin_ifname) != 0) + continue; + + /*portchannel down*/ + if(po_state == 0) + { + #if 1 + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down,flag %d del MAC: %s, MAC %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + if(mac_msg->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + { + /*send mac del message to mclagsyncd.*/ + if(mac_msg->fdb_type != MAC_TYPE_STATIC) + del_mac_from_chip(mac_msg); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, del MAC: %s, MAC %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + /*If local and peer both aged, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, flag %d redirect MAC to peer-link: %s, MAC %s vlan-id %d", + mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + /*First del the old item*/ + /*del_mac_from_chip(mac_msg);*/ + + /*If local is aged but peer is not aged, redirect the mac to peer-link*/ + memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + + /*sleep 10ms, avoid orchagent mix the del event*/ + /*usleep(100000);*/ + + /*Send mac add message to mclagsyncd. fdb_type is not changed*/ + /*Is need to delete the old item before add?(Old item probably is static)*/ + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + #endif + } + else /*portchannel up*/ + { + if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf up, redirect MAC to portchannel: %s, MAC %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + /*Remove MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm,mac_msg, 0); + + /*Send mac del message to mclagsyncd, current port is peer-link*/ + /*del_mac_from_chip(mac_msg);*/ + + /*Reverse interface from peer-link to the original portchannel*/ + memcpy(mac_msg->ifname, mac_msg->origin_ifname, MAX_L_PORT_NAME); + + /*sleep 10ms, avoid orchagent mix the del event*/ + /*sleep(100000);*/ + + /*Send dynamic or static mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, mac_msg->fdb_type); + } + } + } + + return; +} + +void mlacp_portchannel_state_handler(struct CSM* csm, + struct LocalInterface* local_if, + int po_state) +{ + if (!csm || !local_if) + return; + + update_peerlink_isolate_from_lif(csm, local_if, po_state); + + update_l2_mac_state(csm, local_if, po_state); + + if(!local_if_is_l3_mode(local_if)) + update_l2_po_state(csm, local_if, po_state); + else + update_l3_po_state(csm, local_if, po_state); + + update_po_if_info(csm, local_if, po_state); + + return; +} + +static void mlacp_conn_handler_fdb (struct CSM* csm) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + struct Msg *msg_send = NULL; + + if (!csm) + return; + + if(!TAILQ_EMPTY(&(MLACP(csm).mac_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*) msg->buf; + + /*Wait the ACK from peer?*/ + /*mac_msg->age_flag &= ~MAC_AGE_PEER;*/ + + /*Send mac add message to peer*/ + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } + + return; +} + +/***************************************** +* Peer-Link connect/disconnect handler +* +* ***************************************/ +void mlacp_peerlink_conn_handler(struct CSM* csm) +{ + struct LocalInterface *lif = NULL; + struct PeerInterface *pif = NULL; + struct VLAN_ID *vlan = NULL; + static int first_time = 0; + + if (!csm) + return; + + set_peerlink_mlag_port_learn(csm->peer_link_if, 0); + + if(first_time == 0) + { + first_time = 1; + mlacp_clean_fdb(); + } + + iccp_get_fdb_change_from_syncd(); + + mlacp_conn_handler_fdb(csm); + +#if 0 + // When peer-link ready, suppose all MLAG link are alive + LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) + { + pif->po_active = 1; + } +#endif + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if(lif->type == IF_T_PORT_CHANNEL) + { + if(local_if_is_l3_mode(lif)) + { + set_route_by_linux_route( csm, lif, 1); + } + else + { + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if(!vlan->vlan_itf) + continue; + if(!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + set_route_by_linux_route(csm, vlan->vlan_itf, 1); /* add static route by linux route tool*/ + } + } + + mlacp_portchannel_state_handler(csm, lif,(lif->state==PORT_STATE_UP)?1:0); + } + } + + return; +} + +void mlacp_peerlink_disconn_handler(struct CSM* csm) +{ +/*If peer disconnect, remove all the mac that point to the peer-link, +do not clean static route,arp,port block, ARP will ageout, port block +will recalculate after peer connected.*/ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + + if (!csm) + return; + + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*) msg->buf; + + mac_msg->age_flag |= MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + + /* find the MAC that the port is peer-link*/ + if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer disconnect, del MAC for peer-link: %s, MAC %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + /*Send mac del message to mclagsyncd*/ + del_mac_from_chip(mac_msg); + + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + +#if 0 + struct LocalInterface *local_if=NULL; + struct VLAN_ID *vlan=NULL; + + if (!csm) + return; + + /*set_peerlink_mlag_port_learn(csm, 1);*/ + + /* Clean all L3 static route & arp info*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if(local_if->type == IF_T_PORT_CHANNEL) { + set_peerlink_mlag_port_isolate(csm, local_if, 0); + + if(local_if_is_l3_mode(local_if)){ + /*set_route_by_linux_route(csm, local_if, 0);*/ /* del static route by linux route tool*/ + arp_set_handler(csm, local_if, 0); /* del arp*/ + } + else { + LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) + { + if(!vlan->vlan_itf) + continue; + if(!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + /*set_route_by_linux_route(csm, vlan->vlan_itf, 0);*/ /*del static route by linux route tool*/ + arp_set_handler(csm, vlan->vlan_itf, 0); /* del arp*/ + } + } + } + } +#endif + + return; +} + +/***************************************** +* Po add/remove handler +* +*****************************************/ +void mlacp_mlag_link_add_handler(struct CSM *csm, struct LocalInterface *lif) +{ + if (!csm || !lif) + return; + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + set_peerlink_mlag_port_isolate(csm, lif, 1); + + return; +} + +void mlacp_mlag_link_del_handler(struct CSM *csm, struct LocalInterface *lif) +{ + if (!csm || !lif) + return; + + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + set_peerlink_mlag_port_isolate(csm, lif, 0); + + return; +} + +/***************************************** +* Tool : show ip string +* +* ***************************************/ +char *show_ip_str(uint32_t ipv4_addr) +{ + struct in_addr in_addr; + + memset(g_ipv4_str, 0 ,sizeof(g_ipv4_str)); + in_addr.s_addr = ipv4_addr; + inet_ntop(AF_INET, &in_addr, g_ipv4_str, INET_ADDRSTRLEN); + + return g_ipv4_str; +} + +int iccp_connect_syncd() +{ + struct System* sys = NULL; + int ret = 0; + int fd = 0; + struct sockaddr_in serv; + static int count = 0; + + if ((sys = system_get_instance()) == NULL) + goto conn_fail; + + if(sys->sync_fd >= 0) + return 0; + + /*Print the fail log message every 60s*/ + if(count >= 600) + { + count = 0; + } + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + { + if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to create unix socket: %s", strerror(errno)); + goto conn_fail; + } + + /* Make server socket. */ + memset(&serv, 0, sizeof(serv)); + serv.sin_family = AF_INET; + serv.sin_port = htons(2626); +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + serv.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + serv.sin_addr.s_addr = htonl(0x7f000006); + + ret = connect(fd, (struct sockaddr *)&serv, sizeof(serv)); + if (ret < 0) { + if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to connect to mclag syncd: errno str %s", strerror(errno)); + close(fd); + goto conn_fail; + } + + ICCPD_LOG_WARN(__FUNCTION__, "success to link syncd"); + sys->sync_fd = fd; + + struct epoll_event event; + int err; + event.data.fd = fd; + event.events = EPOLLIN; + ret = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, fd, &event); + + count = 0; + return 0; + +conn_fail: + if(count == 0) ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclag syncd socket connect fail", + __FUNCTION__, __LINE__); + + count++; + + return -1; +} + +void syncd_info_close() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + if(sys->sync_fd > 0) + { + close(sys->sync_fd); + sys->sync_fd = -1; + } + + return; +} + + int iccp_get_receive_fdb_sock_fd(struct System *sys) +{ + return sys->sync_fd; +} + + int iccp_receive_fdb_handler_from_syncd(struct System *sys) +{ + int n=0; + int count = 0; + int i =0; + int need_free = 0; + char *msg_buf = g_csm_buf; + struct LocalInterface* lif = NULL; + struct IccpSyncdHDr * msg_hdr; + struct mclag_fdb_info * mac_info; + static time_t last_time = 0; + char* data = &msg_buf[sizeof(struct IccpSyncdHDr)]; + + if(sys == NULL) + return -1; + memset(msg_buf, 0, CSM_BUFFER_SIZE); + + n = read(sys->sync_fd, msg_buf, CSM_BUFFER_SIZE); + if (n <=0) + { + if (last_time == 0 || (time(NULL) - last_time) >= 60) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d read error ret = %d errno = %d ",sys->sync_fd, n, errno); + last_time = time(NULL); + } + + return -1; + } + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg version %d type %d len %d ",msg_hdr->ver , msg_hdr->type, msg_hdr->len ); + if (msg_hdr->ver != 1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "msg version wrong!!!!! "); + return -1; + } + + if (msg_hdr->type != MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "msg type wrong!!!!! "); + return -1; + } + + count =( msg_hdr->len- sizeof(struct IccpSyncdHDr ))/sizeof(struct mclag_fdb_info); + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d ",count ); + for (i =0; ivid, mac_info->mac, mac_info->port_name, mac_info->op_type); + lif = local_if_find_by_name(mac_info->port_name); + + /*if (!lif ||lif->type != IF_T_PORT_CHANNEL)*/ + if (!lif) + continue; + + do_mac_update_from_syncd(mac_info->mac, mac_info->vid, mac_info->port_name, mac_info->type, mac_info->op_type); + } + + return 0; +} + +char * mclagd_ctl_cmd_str(int req_type) +{ + switch (req_type) + { + case INFO_TYPE_DUMP_STATE: + return "dump config"; + case INFO_TYPE_DUMP_ARP: + return "dump arp"; + case INFO_TYPE_DUMP_MAC: + return "dump mac"; + case INFO_TYPE_DUMP_LOCAL_PORTLIST: + return "dump local portlist"; + case INFO_TYPE_DUMP_PEER_PORTLIST: + return "dump peer portlist"; + default: + break; + } + + return "error req type"; +} + +int mclagd_ctl_sock_create() +{ + struct sockaddr_un addr; + struct System* sys = NULL; + struct epoll_event event; + int addr_len; + int ret = 0; + + if ((sys = system_get_instance()) == NULL) + return -1;; + + if(sys->sync_ctrl_fd > 0) + return sys->sync_ctrl_fd; + + sys->sync_ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if(sys->sync_ctrl_fd < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to create mclagd ctl sock\n"); + return sys->sync_ctrl_fd; + } + + unlink(sys->mclagdctl_file_path); + + memset((void*)&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, 107, "%s", sys->mclagdctl_file_path); + addr_len = sizeof(addr.sun_family) + strlen(sys->mclagdctl_file_path); + + if((ret = bind(sys->sync_ctrl_fd, (struct sockaddr*)&addr, addr_len)) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to bind mclagd ctl socket %s:%s\n", sys->mclagdctl_file_path, strerror(errno)); + close(sys->sync_ctrl_fd); + return -1; + } + + if(listen(sys->sync_ctrl_fd, 5) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to listen unix mclagd ctl socket%s:%s\n", sys->mclagdctl_file_path, strerror(errno)); + close(sys->sync_ctrl_fd); + return -1; + } + + event.data.fd = sys->sync_ctrl_fd; + event.events = EPOLLIN; + epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, sys->sync_ctrl_fd, &event); + FD_SET(sys->sync_ctrl_fd, &(sys->readfd)); + sys->readfd_count++; + + return sys->sync_ctrl_fd; +} + +int mclagd_ctl_sock_accept(int fd) +{ + struct sockaddr_in client_addr; + int client_fd = 0; + unsigned int addr_len = 0; + + client_fd = accept(fd, (struct sockaddr*)&client_addr, &addr_len); + if(client_fd < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "failed to accept a client from mclagdctl\n"); + return -1; + } + + return client_fd; +} + +int mclagd_ctl_sock_read(int fd, unsigned char *r_buf ,int total_len) +{ + int read_len=0; + int ret=0; + struct timeval tv = {0}; + fd_set read_fd; + + while(read_len < total_len) + { + FD_ZERO(&read_fd); + FD_SET(fd, &read_fd); + tv.tv_sec = 5; + tv.tv_usec = 0; + + switch ((ret = select(fd + 1, &read_fd, NULL, NULL, &tv))) + { + case -1: + /* error*/ + case 0: + /* timeout*/ + return -1; + default: + break; + } + if(FD_ISSET(fd, &read_fd)) + ret = read(fd, r_buf + read_len, total_len - read_len); + if(ret <= 0) + { + return -1; + } + read_len += ret; + } + + return read_len; +} + +int mclagd_ctl_sock_write(int fd, unsigned char *w_buf ,int total_len) +{ + int write_len =0; + int ret=0; + + while(write_len < total_len) + { + ret = write(fd, w_buf + write_len, total_len - write_len); + if(ret <= 0) + { + return 0; + } + write_len += ret; + } + + return write_len; +} + +void mclagd_ctl_handle_dump_state(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int state_num = 0; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_mclag_config_dump(&Pbuf, &state_num, mclag_id); + ICCPD_LOG_WARN(__FUNCTION__, "state_num = %d", state_num); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_STATE; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_STATE; + hd->data_len = state_num * sizeof(struct mclagd_state); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_arp(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int arp_num = 0; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_arp_dump(&Pbuf, &arp_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_ARP; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_ARP; + hd->data_len = arp_num * sizeof(struct mclagd_arp_msg); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_mac(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int mac_num = 0; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_mac_dump(&Pbuf, &mac_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_MAC; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_MAC; + hd->data_len = mac_num * sizeof(struct mclagd_mac_msg); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_local_portlist(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int lif_num = 0;; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_local_if_dump(&Pbuf, &lif_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; + hd->data_len = lif_num * sizeof(struct mclagd_local_if); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_peer_portlist(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int pif_num = 0; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_peer_if_dump(&Pbuf, &pif_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_PEER_PORTLIST; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_PEER_PORTLIST; + hd->data_len = pif_num * sizeof(struct mclagd_peer_if); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +int mclagd_ctl_interactive_process(int client_fd) +{ + char buf[512] = {0}; + int ret = 0; + + struct mclagdctl_req_hdr* req = NULL; + + if (client_fd < 0) + return -1; + + ret = mclagd_ctl_sock_read(client_fd, buf, sizeof(struct mclagdctl_req_hdr)); + + if (ret < 0) + return -1; + + req = (struct mclagdctl_req_hdr*)buf; + + ICCPD_LOG_WARN(__FUNCTION__, "rcv request %s from mclagdctl", mclagd_ctl_cmd_str(req->info_type)); + + switch (req->info_type) + { + case INFO_TYPE_DUMP_STATE: + mclagd_ctl_handle_dump_state(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_ARP: + mclagd_ctl_handle_dump_arp(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_MAC: + mclagd_ctl_handle_dump_mac(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_LOCAL_PORTLIST: + mclagd_ctl_handle_dump_local_portlist(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_PEER_PORTLIST: + mclagd_ctl_handle_dump_peer_portlist(client_fd, req->mclag_id); + break; + default: + return -1; + } + + return 0; +} + + diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c new file mode 100644 index 000000000000..27a2ad9c00d0 --- /dev/null +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -0,0 +1,789 @@ +/* +* MLACP Sync Infomation Preparation +* mlacp_sync_prepare.c + +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +* +*/ + +#include +#include + +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_fsm.h" +#include "../include/mlacp_tlv.h" +#include "../include/mlacp_link_handler.h" +#include "../include/iccp_ifm.h" + +#define SET_MAC_STR(buf, macArray) \ + snprintf(buf, 64, "%02x:%02x:%02x:%02x:%02x:%02x",\ + macArray[0],macArray[1],macArray[2], \ + macArray[3],macArray[4],macArray[5]); + +#define SYSID_UPDATE_INT 3 /*3 secs*/ + +void update_system_id(struct CSM* csm) +{ + char macaddr[64]; + char ori_macaddr[64]; + struct LocalInterface* lif_po = NULL; + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + char cmd[256]; + int ret = 0; + static int bridge_mac_set = 0; + struct VLAN_ID *vlan = NULL; + + if (!csm) + return; + + if(memcmp(MLACP(csm).system_id, null_mac, ETHER_ADDR_LEN)==0) + return; + + if(memcmp(MLACP(csm).remote_system.system_id, null_mac, ETHER_ADDR_LEN)==0) + return; + + /* don't change mac continously, it needs a little time to process mac*/ + if ((time(NULL)-csm->sysid_update_time) < SYSID_UPDATE_INT) + return; + + time(&csm->sysid_update_time); + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if(lif_po->type != IF_T_PORT_CHANNEL) + continue; + + /* backup old sysmac*/ + memcpy(lif_po->mac_addr_ori, lif_po->mac_addr, + ETHER_ADDR_LEN); + + /* set new mac*/ + memset(macaddr, 0, 64); + memset(ori_macaddr, 0, 64); + + SET_MAC_STR(ori_macaddr, lif_po->mac_addr); + + if (csm->role_type == STP_ROLE_STANDBY) + { + SET_MAC_STR(macaddr, MLACP(csm).remote_system.system_id); + } + else + { + SET_MAC_STR(macaddr, MLACP(csm).system_id); + } + + if(strcmp(macaddr, ori_macaddr)!= 0) + { + ICCPD_LOG_INFO(__FUNCTION__, + "%s Change the system-id of po%d from %s to %s.", + (csm->role_type == STP_ROLE_STANDBY)?"Standby":"Active", + lif_po->po_id, ori_macaddr, macaddr); + + snprintf(cmd, sizeof cmd, + "ip link set dev %s address %s > /dev/null 2>&1", + lif_po->name, macaddr); + ret = system(cmd); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "%s: Execute command (%s) ret = %d", + __FUNCTION__, cmd, ret); + } + + if(local_if_is_l3_mode(lif_po)) + iccp_set_portchannel_ipadd_mac(lif_po, macaddr ); + else + { + LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) + { + if(!vlan->vlan_itf) + continue; + + /* If the po is under a vlan, update vlan mac*/ + if(local_if_is_l3_mode(vlan->vlan_itf)) + { + snprintf(cmd, sizeof cmd, + "ip link set dev %s address %s > /dev/null 2>&1", + vlan->vlan_itf->name, macaddr); + ret = system(cmd); + + iccp_set_portchannel_ipadd_mac(vlan->vlan_itf, macaddr ); + } + } + } + + /*Set bridge mac, prevent bridge mac changed follow portchannel mac*/ + if(bridge_mac_set == 0) + { + bridge_mac_set = 1; + + snprintf(cmd, sizeof cmd, + "ip link set dev Bridge address %s > /dev/null 2>&1", + ori_macaddr); + + ret = system(cmd); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "%s: Execute command (%s) ret = %d", + __FUNCTION__, cmd, ret); + } + } + } + } + + return; +} + +/***************************************** +* Static Function +* +* ***************************************/ +static int mlacp_fill_icc_header(struct CSM* csm, ICCHdr* icc_hdr, size_t msg_len); + +/***************************************** +* Sync portchannel state and MAC with kernel +* +* ***************************************/ +int mlacp_sync_with_kernel_callback() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); + goto out; + } + + /* traverse all CSM */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + /* Sync MLAG po state with kernel*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if(local_if->type == IF_T_PORT_CHANNEL) + { + /* sync system info from one port-channel device*/ + if(memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) + { + memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); + MLACP(csm).system_config_changed = 1; + + update_system_id(csm); + + break; + } + } + } + } + +out: + return 0; +} + + +/***************************************** +* Create Sync Request TLV +* +* ***************************************/ +int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = NULL; + mLACPSyncReqTLV* tlv = NULL; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncReqTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPSyncReqTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* mLACP Synchronization Request TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPSyncReqTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_SYNC_REQUEST; + + tlv->req_num = 0; + MLACP(csm).sync_req_num = tlv->req_num; + tlv->c_bit = 1; + tlv->s_bit = 1; + tlv->req_type = 0x3FFF; + tlv->port_num_agg_id = 0; + tlv->actor_key = 0; + + return msg_len; +} + +/***************************************** +* Prprare Sync Data TLV +* +* ***************************************/ +int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*) buf; + mLACPSyncDataTLV* tlv = (mLACPSyncDataTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncDataTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPSyncDataTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* mLACP Synchronization Data TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPSyncDataTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_SYNC_DATA; + + tlv->req_num = MLACP(csm).sync_req_num; + if(end == 0) + tlv->flags = 0x00; + else + tlv->flags = 0x01; + + return msg_len; +} + +/***************************************** +* Prprare Sync System-Config TLV +* +* ***************************************/ +int mlacp_prepare_for_sys_config(struct CSM* csm,char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*) buf; + mLACPSysConfigTLV* tlv = (mLACPSysConfigTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSysConfigTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPSysConfigTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* System Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPSysConfigTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_SYSTEM_CONFIG; + + memcpy(tlv->sys_id, MLACP(csm).system_id, ETHER_ADDR_LEN); + tlv->sys_priority = MLACP(csm).system_priority; + tlv->node_id = MLACP(csm).node_id; + return msg_len; +} + +/*Prprare Sync AggPort-State TLV */ +int mlacp_prepare_for_Aggport_state(struct CSM* csm,char* buf, size_t max_buf_size, struct LocalInterface* local_if) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*) buf; + mLACPAggPortStateTLV* tlv = (mLACPAggPortStateTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggPortStateTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(local_if == NULL) + return -1; + + if(local_if->type != IF_T_PORT_CHANNEL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPAggPortStateTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port State TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPAggPortStateTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_AGGREGATOR_STATE; + + tlv->partner_sys_priority = 0; + tlv->partner_key = 0; + tlv->agg_id = local_if->po_id; + tlv->actor_key = 0; + tlv->agg_state = local_if->state; + + return msg_len; +} + +/***************************************** +* Prprare Sync Purge Port +* +* ***************************************/ +int mlacp_prepare_for_Aggport_config(struct CSM* csm, + char* buf, size_t max_buf_size, + struct LocalInterface* lif, int purge_flag) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + mLACPAggConfigTLV* tlv = (mLACPAggConfigTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggConfigTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPAggConfigTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPAggConfigTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_AGGREGATOR_CONFIG; + + tlv->agg_id = lif->po_id; + if(purge_flag == 1) + tlv->flags = 0x02; /*purge*/ + else + tlv->flags = 0x1; + tlv->agg_name_len = strlen(lif->name); + memcpy(tlv->agg_name, lif->name, MAX_L_PORT_NAME); + memcpy(tlv->mac_addr, lif->mac_addr, ETHER_ADDR_LEN); + + return msg_len; +} + +/***************************************** +* Preprare Sync MAC-Info TLV +* +* ***************************************/ +int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg) +{ + struct mLACPMACInfoTLV* tlv = NULL; + size_t msg_len = 0; + size_t tlv_len = 0; + ICCHdr* icc_hdr = NULL; + + if (!csm) + return -1; + if (!buf) + return -1; + + tlv_len = sizeof(struct mLACPMACInfoTLV); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return -1; + + /* ICC header */ + memset(buf, 0, max_buf_size); + icc_hdr = (ICCHdr*) buf; + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Prepare for ARP information TLV */ + tlv = (struct mLACPMACInfoTLV*) malloc(tlv_len); + memset(tlv, 0, tlv_len); + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = TLV_T_MLACP_MAC_INFO; + tlv->icc_parameter.len = tlv_len - sizeof(ICCParameter); + tlv->type = mac_msg->op_type; + sprintf(tlv->mac_str, "%s", mac_msg->mac_str); + sprintf(tlv->ifname, "%s", mac_msg->origin_ifname); + tlv->vid = mac_msg->vid; + + /* Fill MAC Information TLV */ + memcpy(&buf[sizeof(ICCHdr)], tlv, tlv_len); + free(tlv); + + #if 1 + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg type = TLV_T_MLACP_MAC_INFO"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s mac = %s, vid = %d, type = %d", mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + #endif + + return msg_len; +} + +/***************************************** +* Preprare Sync ARP-Info TLV +* +* ***************************************/ +int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg) +{ + struct mLACPARPInfoTLV* tlv = NULL; + size_t msg_len = 0; + size_t tlv_len = 0; + ICCHdr* icc_hdr = NULL; + + if (!csm) + return -1; + if (!buf) + return -1; + + tlv_len = sizeof(struct mLACPARPInfoTLV); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return -1; + + /* ICC header */ + memset(buf, 0, max_buf_size); + icc_hdr = (ICCHdr*) buf; + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Prepare for ARP information TLV */ + tlv = (struct mLACPARPInfoTLV*) malloc(tlv_len); + memset(tlv, 0, tlv_len); + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = TLV_T_MLACP_ARP_INFO; + tlv->icc_parameter.len = tlv_len - sizeof(ICCParameter); + tlv->type = arp_msg->op_type; + sprintf(tlv->ifname, "%s", arp_msg->ifname); + tlv->ipv4_addr = arp_msg->ipv4_addr; + memcpy(tlv->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + + /* Fill ARP Information TLV */ + memcpy(&buf[sizeof(ICCHdr)], tlv, tlv_len); + free(tlv); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s msg ifname %s mac =%02x:%02x:%02x:%02x:%02x:%02x ", tlv->ifname, arp_msg->ifname, tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], + tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + ICCPD_LOG_DEBUG(__FUNCTION__, " IP Addr = %s ",show_ip_str( tlv->ipv4_addr)); + + return msg_len; +} + +/***************************************** +* Prprare Send portchannel info +* +* ***************************************/ +int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, + size_t max_buf_size, + struct LocalInterface* port_channel) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = NULL; + struct mLACPPortChannelInfoTLV* tlv = NULL; + size_t msg_len; + size_t tlv_len; + size_t name_len = MAX_L_PORT_NAME; + struct VLAN_ID* vlan_id = NULL; + int num_of_vlan_id = 0; + + if (csm == NULL ) + return -1; + if (buf == NULL ) + return -1; + if (port_channel == NULL ) + return -1; + if (port_channel->type == IF_T_PORT) + return -1; + if ((sys = system_get_instance()) == NULL ) + return -1; + + /* Calculate VLAN ID Length */ + LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next) + if (vlan_id != NULL) num_of_vlan_id++; + + tlv_len = sizeof(struct mLACPPortChannelInfoTLV) + sizeof(struct VLAN_ID) * num_of_vlan_id; + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return -1; + + /* Prepare for port channel info */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (struct mLACPPortChannelInfoTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port Channel Info TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(struct mLACPPortChannelInfoTLV) - sizeof(ICCParameter) + sizeof(struct VLAN_ID) *num_of_vlan_id ; + tlv->icc_parameter.type = TLV_T_MLACP_PORT_CHANNEL_INFO; + tlv->agg_id = port_channel->po_id; + tlv->ipv4_addr = htonl(port_channel->ipv4_addr); + tlv->l3_mode = port_channel->l3_mode; + tlv->po_id = port_channel->po_id; + + if(strlen(port_channel->name) < name_len) + name_len = strlen(port_channel->name); + memcpy(tlv->if_name, port_channel->name, name_len); + tlv->if_name_len = name_len; + tlv->num_of_vlan_id = num_of_vlan_id; + + num_of_vlan_id = 0; + LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next) + { + if (vlan_id != NULL ) + { + tlv->vlanData[num_of_vlan_id].vlan_id = vlan_id->vid; + + num_of_vlan_id++; + ICCPD_LOG_DEBUG(__FUNCTION__, " port channel %d: addr = %s vlan id %d num %d ", port_channel->po_id, show_ip_str( tlv->ipv4_addr), vlan_id->vid, num_of_vlan_id ); + } + } + + ICCPD_LOG_DEBUG(__FUNCTION__, " port channel %d: addr = 0x%08x l3 mode %d", port_channel->po_id, tlv->ipv4_addr, tlv->l3_mode); + + return msg_len; +} + +/***************************************** +* Prprare Send port peerlink info +* +* ***************************************/ +int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, + size_t max_buf_size, + struct LocalInterface* peerlink_port) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = NULL; + struct mLACPPeerLinkInfoTLV* tlv = NULL; + size_t msg_len; + size_t tlv_len; + + if (csm == NULL ) + return -1; + if (buf == NULL ) + return -1; + if (peerlink_port == NULL ) + return -1; + if ((sys = system_get_instance()) == NULL ) + return -1; + + /* Prepare for port channel info */ + memset(buf, 0, max_buf_size); + + tlv_len = sizeof(struct mLACPPeerLinkInfoTLV); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return -1; + + icc_hdr = (ICCHdr*) buf; + tlv = (struct mLACPPeerLinkInfoTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port Channel Info TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = tlv_len - sizeof(ICCParameter) ; + tlv->icc_parameter.type = TLV_T_MLACP_PEERLINK_INFO; + + memcpy(tlv->if_name, peerlink_port->name, MAX_L_PORT_NAME); + tlv->port_type = peerlink_port->type; + + + ICCPD_LOG_DEBUG(__FUNCTION__, " peerlink port info portname %s type = %d", tlv->if_name, tlv->port_type); + + return msg_len; +} + + +/***************************************** +* Prprare Send Heartbeat +* +* ***************************************/ +int mlacp_prepare_for_heartbeat(struct CSM* csm,char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*) buf; + struct mLACPHeartbeatTLV* tlv = (struct mLACPHeartbeatTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPHeartbeatTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (struct mLACPHeartbeatTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* System Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(struct mLACPHeartbeatTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_HEARTBEAT; + + tlv->heartbeat = 0xFF; + return msg_len; +} + +/***************************************** +* Tool : Prepare ICC Header +* +* ***************************************/ +static int mlacp_fill_icc_header(struct CSM* csm, ICCHdr* icc_hdr, size_t msg_len) +{ + if(csm == NULL || icc_hdr == NULL) + return -1; + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_RG_APP_DATA; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID; + ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + return 0; +} + + +/***************************************** +* Tool : Update System ID +* +* ***************************************/ +void iccp_set_portchannel_ipadd_mac(struct LocalInterface *lif,uint8_t * mac_addr ) +{ + struct IccpSyncdHDr * msg_hdr; + mclag_sub_option_hdr_t * sub_msg; + char msg_buf[4096]; + struct System *sys; + + int src_len = 0,dst_len =0; + sys = system_get_instance(); + if(sys == NULL) + return; + + memset(msg_buf,0,4095); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_SET_MAC; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + /*sub msg src*/ + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC; + + src_len = snprintf(sub_msg->data, 512, "%s:%s/%d", lif->name,show_ip_str(htonl(lif->ipv4_addr)),lif->prefixlen); + + sub_msg->op_len = src_len; + + /*sub msg dst */ + msg_hdr->len += sub_msg->op_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_SET_MAC_DST; + + dst_len = strlen(mac_addr); + memcpy(sub_msg->data, mac_addr, dst_len); + + ICCPD_LOG_DEBUG(__FUNCTION__,"lif name %s address %s mac msg data %s %d \n", lif->name , show_ip_str(lif->ipv4_addr), sub_msg->data ,dst_len); + + sub_msg->op_len = dst_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + /*send msg*/ + if(sys->sync_fd) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + + diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c new file mode 100644 index 000000000000..f8c8ddbadefa --- /dev/null +++ b/src/iccpd/src/mlacp_sync_update.c @@ -0,0 +1,741 @@ +/******************************************************************************** +* mlacp_sync_update.c +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +* +*******************************************************************************/ +#include +#include + +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_tlv.h" +#include "../include/mlacp_link_handler.h" + +/***************************************** +* Port-Conf Update +* +* ***************************************/ +int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV*sysconf) +{ + /*NOTE + a little tricky, we change the NodeID local side if collision happened first time*/ + if(sysconf->node_id == MLACP(csm).node_id) + MLACP(csm).node_id++; + + memcpy(MLACP(csm).remote_system.system_id, sysconf->sys_id, ETHER_ADDR_LEN); + MLACP(csm).remote_system.system_priority = sysconf->sys_priority; + MLACP(csm).remote_system.node_id = sysconf->node_id; + + update_system_id(csm); + + ICCPD_LOG_DEBUG(__FUNCTION__, " SystemID [%02X:%02X:%02X:%02X:%02X:%02X]. SystemPriority [%d], Remote NodeID [%d], NodeID [%d]", + MLACP(csm).remote_system.system_id[0],MLACP(csm).remote_system.system_id[1],MLACP(csm).remote_system.system_id[2], + MLACP(csm).remote_system.system_id[3],MLACP(csm).remote_system.system_id[4],MLACP(csm).remote_system.system_id[5], + MLACP(csm).remote_system.system_priority, + MLACP(csm).remote_system.node_id, + MLACP(csm).node_id); + + return 0; +} + +/***************************************** +* Port-Conf Update +* +* ***************************************/ +int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf) +{ + struct PeerInterface* pif = NULL; + uint8_t po_active; + uint8_t new_create = 0; + + ICCPD_LOG_DEBUG(__FUNCTION__, " Port name %s, po id %d flag %d MAC[%02x:%02x:%02x:%02x:%02x:%02x] ", + portconf->agg_name,portconf->agg_id, portconf->flags,portconf->mac_addr[0], portconf->mac_addr[1], portconf->mac_addr[2], + portconf->mac_addr[3], portconf->mac_addr[4], portconf->mac_addr[5] ); + + /* Looking for the peer port instance, is any peer if exist?*/ + pif = peer_if_find_by_name(csm, portconf->agg_name); + + /* Process purge*/ + if (portconf->flags & 0x02) + { + /*Purge*/ + if (pif != NULL ) + peer_if_destroy(pif); + else + MLACP(csm).need_to_sync = 1; + /*ICCPD_LOG_INFO("mlacp_fsm", + " Peer port %s is removed from port-channel member.",portconf->port_name);*/ + + return 0; + } + + if(pif == NULL && portconf->flags & 0x01) + { + pif = peer_if_create(csm, portconf->agg_id, IF_T_PORT_CHANNEL); + if(pif == NULL) return -1; + + new_create= 1; + } + + pif->po_id = portconf->agg_id; + memcpy(pif->name, portconf->agg_name, portconf->agg_name_len); + memcpy(pif->mac_addr, portconf->mac_addr, ETHER_ADDR_LEN); + + po_active = (pif->state == PORT_STATE_UP); + update_stp_peer_link(csm, pif, po_active, new_create); + update_peerlink_isolate_from_pif(csm, pif, po_active, new_create); + pif->po_active = po_active; + + return 0; +} + +/***************************************** +* Agg Port-State Update +* +* ***************************************/ +int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) +{ + struct PeerInterface* peer_if = NULL; + uint8_t po_active; + + if(csm == NULL || tlv == NULL) + return -255; + ICCPD_LOG_DEBUG(__FUNCTION__, " po id %d state %d ",tlv->agg_id, tlv->agg_state); + + po_active = (tlv->agg_state == PORT_STATE_UP); + + LIST_FOREACH(peer_if, &(MLACP(csm).pif_list), mlacp_next) + { + if (peer_if->type != IF_T_PORT_CHANNEL) + continue; + + if (peer_if->po_id != tlv->agg_id) + continue; + + peer_if->state = tlv->agg_state; + + update_stp_peer_link(csm, peer_if, po_active, 0); + update_peerlink_isolate_from_pif(csm, peer_if, po_active, 0); + + peer_if->po_active = po_active; + break; + } + + return 0; +} + + /* Delete an entry from the ARP cache. */ +int mlacp_fsm_arp_del(char *ifname, uint32_t ip) +{ + struct arpreq arpreq; + struct sockaddr_in *sin; + struct in_addr ina; + int rc; + int sock_fd = 0; + + ICCPD_LOG_DEBUG(__FUNCTION__,"%s: Del arp entry for IP : %s\n", __FUNCTION__, show_ip_str(ip)); + + if(ifname == NULL || ip == 0) + { + return -1; + } + + /*you must add this becasue some system will return "Invlid argument" + because some argument isn't zero */ + memset(&arpreq, 0, sizeof(struct arpreq)); + + sin = (struct sockaddr_in *) &arpreq.arp_pa; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + ina.s_addr = ip; + memcpy(&sin->sin_addr, (char *) &ina, sizeof(struct in_addr)); + + strncpy(arpreq.arp_dev, ifname, 15); + + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if(sock_fd < 0) + { + return -1; + } + + rc = ioctl(sock_fd, SIOCDARP, &arpreq); + if (rc < 0) + { + close(sock_fd); + return -1; + } + + close(sock_fd); + + return 0; + } + + int getHwAddr(char *buff, char *mac) + { + int i = 0; + unsigned int p[6]; + + if( buff == NULL || mac == NULL ) + { + return -1; + } + + if(sscanf(mac, "%x:%x:%x:%x:%x:%x", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]) < 6) + { + return -1; + } + + for(i = 0; i < 6; i ++) + { + buff[i] = p[i]; + } + + return 0; + } + + /***************************************** + * Recv from peer, MAC-Info Update + * ***************************************/ + int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* tlv) + { + struct Msg* msg = NULL; + struct Msg* msg_send = NULL; + struct MACMsg *mac_msg = NULL, mac_data; + struct LocalInterface* local_if = NULL; + + if (!csm || !tlv) + return -255; + +#if 1 + ICCPD_LOG_INFO(__FUNCTION__, + "Received MAC Info, itf=[%s] vid[%d] MAC[%s] type %d ", + tlv->ifname, tlv->vid, tlv->mac_str, tlv->type); +#endif + + /*Find the interface*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL && strcmp(local_if->name, tlv->ifname) == 0) + { + break; + } + } + + if(!local_if) + { + /*If the interface is not exist, return*/ + return -255; + } + + /* update MAC list*/ + TAILQ_FOREACH(msg, &(MLACP(csm).mac_list), tail) + { + mac_msg = (struct MACMsg*) msg->buf; + if (strcmp(mac_msg->mac_str, tlv->mac_str) == 0 && mac_msg->vid == tlv->vid) + { + if(tlv->type == MAC_SYNC_ADD) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + + /*mac_msg->fdb_type = tlv->fdb_type;*/ + if(strcmp(mac_msg->ifname, tlv->ifname) != 0 || strcmp(mac_msg->origin_ifname, tlv->ifname) != 0) + { + if(mac_msg->fdb_type != MAC_TYPE_STATIC) + { + memcpy(&mac_msg->ifname, tlv->ifname, MAX_L_PORT_NAME); + memcpy(&mac_msg->origin_ifname, tlv->ifname, MAX_L_PORT_NAME); + } + + if(local_if->state == PORT_STATE_DOWN && strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) + { + /*First del the old item*/ + /*del_mac_from_chip(mac_msg);*/ + + /*If local if is down, redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + + /*sleep 10ms, avoid orchagent mix the del event*/ + /*usleep(100000);*/ + + /*Send mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + } + + #if 0 + mac_msg->op_type = MAC_SYNC_ACK; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + /*Reply mac ack message to peer, peer will clean MAC_AGE_PEER flag*/ + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, MAC-msg-list enqueue: %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + } + #endif + } + else if(tlv->type == MAC_SYNC_ACK) + { + /*Clean the MAC_AGE_PEER flag*/ + mac_msg->age_flag &= ~MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ACK, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + } + + break; + } + } + + /* delete/add MAC list*/ + if (msg && tlv->type == MAC_SYNC_DEL) + { + mac_msg->age_flag |= MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + + if(mac_msg->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + { + /*send mac del message to mclagsyncd.*/ + del_mac_from_chip(mac_msg); + + /*If local and peer both aged, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else + { + return 0; + } + } + else if (!msg && tlv->type == MAC_SYNC_ADD) + { + mac_msg = (struct MACMsg*) &mac_data; + mac_msg->fdb_type = MAC_TYPE_DYNAMIC; + mac_msg->vid = tlv->vid; + sprintf(mac_msg->mac_str, "%s", tlv->mac_str); + sprintf(mac_msg->ifname, "%s", tlv->ifname); + sprintf(mac_msg->origin_ifname, "%s", tlv->ifname); + mac_msg->age_flag = 0; + + if(local_if->state == PORT_STATE_DOWN) + { + /*If local if is down, redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + } + + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); + /*ICCPD_LOG_INFO(__FUNCTION__, "add mac queue successfully");*/ + + /*Send mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, mac_msg->fdb_type); + + #if 0 + mac_msg->op_type = MAC_SYNC_ACK; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + /*Reply mac ack message to peer, peer will clean MAC_AGE_PEER flag*/ + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + } + #endif + } + } + + return 0; + } + + /* Set an entry in the ARP cache. */ +int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac) +{ + struct arpreq arpreq; + struct sockaddr_in *sin; + struct in_addr ina; + int flags; + int rc; + int sock_fd = 0; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Set arp entry for IP:%s MAC:%s ifname:%s\n", show_ip_str(ip), mac,ifname); + + if(ifname == NULL || ip == 0 || mac == NULL) + { + return -1; + } + + /*you must add this becasue some system will return "Invlid argument" + because some argument isn't zero */ + memset(&arpreq, 0, sizeof(struct arpreq)); + sin = (struct sockaddr_in *) &arpreq.arp_pa; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + ina.s_addr = ip; + memcpy(&sin->sin_addr, (char *) &ina, sizeof(struct in_addr)); + + if(getHwAddr((char *)arpreq.arp_ha.sa_data, mac) < 0) + { + return -1; + } + + strncpy(arpreq.arp_dev, ifname, 15); + + flags = ATF_COM; //note, must set flag, if not,you will get error + + arpreq.arp_flags = flags; + + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if(sock_fd < 0) + { + return -1; + } + + rc = ioctl(sock_fd, SIOCSARP, &arpreq); + if (rc < 0) + { + close(sock_fd); + return -1; + } + + close(sock_fd); + + return 0; +} + +/***************************************** +* Tool : Add ARP Info into ARP list +* +****************************************/ +void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg) +{ + struct ARPMsg *arp_msg = NULL; + + if (!csm) + { + if (msg) + free(msg); + return; + } + if (!msg) + return; + + arp_msg = (struct ARPMsg*) msg->buf; + if (arp_msg->op_type != ARP_SYNC_DEL) + { + time(&arp_msg->update_time); + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_list), msg, tail); + } + + return; +} + +/***************************************** +* ARP-Info Update +* ***************************************/ +int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) +{ + struct Msg* msg = NULL; + struct ARPMsg *arp_msg = NULL, arp_data; + struct LocalInterface* local_if; + struct LocalInterface *peer_link_if = NULL; + struct VLAN_ID *vlan_id_list=NULL; + int set_arp_flag=0; + char mac_str[18] = ""; + + if (!csm || !tlv) + return -255; + + #if 1 + ICCPD_LOG_INFO(__FUNCTION__, + "%s: Received ARP Info," + "itf=[%s] ARP IP[%s],MAC[%02x:%02x:%02x:%02x:%02x:%02x]", + __FUNCTION__, + tlv->ifname, show_ip_str(tlv->ipv4_addr), + tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], + tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + #endif + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], + tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + + if(strncmp(tlv->ifname,"Vlan",4) == 0) + { + peer_link_if = local_if_find_by_name(csm->peer_itf_name); + + if(!local_if_is_l3_mode(peer_link_if)) + { + /* Is peer-linlk itf belong to a vlan the same as peer?*/ + LIST_FOREACH(vlan_id_list, &(peer_link_if->vlan_list), port_next) + { + if(!vlan_id_list->vlan_itf) + continue; + if(strcmp(vlan_id_list->vlan_itf->name, tlv->ifname)!=0) + continue; + if(!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, + "%s: ==> Find ARP itf on L3 bridge, peer-link %s of %s", + __FUNCTION__, + peer_link_if->name, vlan_id_list->vlan_itf->name); + + /* Peer-link belong to L3 vlan is alive, set the ARP info*/ + set_arp_flag=1; + + break; + } + } + } + + if(set_arp_flag == 0) + { + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) + { + if(!local_if_is_l3_mode(local_if)) + { + /* Is the L2 MLAG itf belong to a vlan the same as peer?*/ + LIST_FOREACH(vlan_id_list, &(local_if->vlan_list), port_next) + { + if(!vlan_id_list->vlan_itf) + continue; + if(strcmp(vlan_id_list->vlan_itf->name, tlv->ifname)!=0) + continue; + if(!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, + "%s: ==> Find ARP itf on L3 bridge, %s of %s", + __FUNCTION__, + local_if->name, vlan_id_list->vlan_itf->name); + break; + } + + if(vlan_id_list && local_if->po_active==1) + { + /* Any po of L3 vlan is alive, set the ARP info*/ + set_arp_flag=1; + break; + } + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf?*/ + if(strcmp(local_if->name, tlv->ifname)==0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, + "%s: ==> Find ARP itf on L3 port-channel, %s", + __FUNCTION__, + local_if->name); + if(local_if->po_active==1) + { + /* po is alive, set the ARP info*/ + set_arp_flag=1; + break; + } + } + else + { + continue; + } + } + } + } + } + + /* set dynamic ARP*/ + if (set_arp_flag == 1) + { + if (tlv->type == ARP_SYNC_ADD) + { + if(mlacp_fsm_arp_set(tlv->ifname, tlv->ipv4_addr, mac_str) < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__,"%s: ARP set for %s %s %s", + __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); + return -1; + } + } + else + { + if(mlacp_fsm_arp_del(tlv->ifname, tlv->ipv4_addr) < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__,"%s: ARP delete for %s %s %s", + __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); + return -1; + } + } + + ICCPD_LOG_DEBUG(__FUNCTION__,"%s: ARP update for %s %s %s", + __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ==> port-channel is not alive", + __FUNCTION__); + /*TODO Set static route through peer-link or just skip it?*/ + } + + /* update ARP list*/ + TAILQ_FOREACH(msg, &(MLACP(csm).arp_list), tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + if (arp_msg->ipv4_addr == tlv->ipv4_addr) + { + /*arp_msg->op_type = tlv->type;*/ + sprintf(arp_msg->ifname, "%s", tlv->ifname); + memcpy(arp_msg->mac_addr, tlv->mac_addr, ETHER_ADDR_LEN); + break; + } + } + + /* delete/add ARP list*/ + if (msg && tlv->type == ARP_SYNC_DEL) + { + TAILQ_REMOVE(&(MLACP(csm).arp_list), msg, tail); + free(msg->buf); free(msg); + ICCPD_LOG_INFO(__FUNCTION__, "%s: del arp queue successfully", + __FUNCTION__); + } + else if (!msg && tlv->type == ARP_SYNC_ADD) + { + arp_msg = (struct ARPMsg*) &arp_data; + sprintf(arp_msg->ifname, "%s", tlv->ifname); + arp_msg->ipv4_addr = tlv->ipv4_addr; + arp_msg->op_type = tlv->type; + memcpy(arp_msg->mac_addr, tlv->mac_addr, ETHER_ADDR_LEN); + if (iccp_csm_init_msg(&msg, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + { + mlacp_enqueue_arp(csm, msg); + ICCPD_LOG_INFO(__FUNCTION__, "%s: add arp queue successfully", + __FUNCTION__); + } + } + + /* remove all ARP msg queue, when receive peer's ARP list at the same time*/ + TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + if (arp_msg->ipv4_addr == tlv->ipv4_addr) break; + } + + while (msg) + { + arp_msg = (struct ARPMsg*) msg->buf; + TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); + free(msg->buf); + free(msg); + TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + if (arp_msg->ipv4_addr == tlv->ipv4_addr) break; + } + } + + return 0; +} + +/***************************************** +* Port-Channel-Info Update +* ***************************************/ +int mlacp_fsm_update_port_channel_info(struct CSM* csm, + struct mLACPPortChannelInfoTLV* tlv) +{ + struct PeerInterface* peer_if = NULL; + struct LocalInterface* local_if = NULL; + struct VLAN_ID* peer_vlan_id = NULL; + int i = 0; + + if (csm == NULL || tlv == NULL ) + return -1; + + LIST_FOREACH(peer_if, &(MLACP(csm).pif_list), mlacp_next) + { + if (peer_if->type != IF_T_PORT_CHANNEL) + continue; + + if (peer_if->po_id != tlv->agg_id) + continue; + + LIST_FOREACH(peer_vlan_id, &(peer_if->vlan_list), port_next) + { + peer_vlan_id->vlan_removed = 1; + } + + /* Record peer info*/ + peer_if->ipv4_addr = ntohl(tlv->ipv4_addr); + peer_if->l3_mode = tlv->l3_mode; + + for (i = 0; i < tlv->num_of_vlan_id; i++) + { + peer_if_add_vlan(peer_if,tlv->vlanData[i].vlan_id); + } + + peer_if_clean_unused_vlan(peer_if); + + iccp_consistency_check(peer_if->name); + + ICCPD_LOG_DEBUG(__FUNCTION__, "port channel info ip %s l3 mode %d", show_ip_str( peer_if->ipv4_addr), peer_if->l3_mode); + break; + } + + return 0; +} + +/***************************************** +* Peerlink port Update +* ***************************************/ +int mlacp_fsm_update_peerlink_info(struct CSM* csm, + struct mLACPPeerLinkInfoTLV* tlv) +{ + if (csm == NULL || tlv == NULL ) + return -1; + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port info from peer"); + + if(csm->peer_link_if->type != tlv->port_type) + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port type of peer %d is not same as local %d !", tlv->port_type, csm->peer_link_if->type); + + /*if(tlv->port_type == IF_T_VXLAN && strncmp(csm->peer_itf_name, tlv->if_name, strlen(csm->peer_itf_name))) + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port is vxlan port and peerlink port at peer %s is not same as local peerlink port %s !",tlv->if_name, csm->peer_itf_name);*/ + + return 0; +} + +/***************************************** +* Heartbeat Update +*****************************************/ +int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv) +{ + if (!csm || !tlv) + return -255; + + time(&csm->heartbeat_update_time); + + return 0; +} + + diff --git a/src/iccpd/src/port.c b/src/iccpd/src/port.c new file mode 100644 index 000000000000..3ebbc3517ef6 --- /dev/null +++ b/src/iccpd/src/port.c @@ -0,0 +1,711 @@ +/* +* port.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include + +#include "../include/logger.h" +#include "../include/port.h" +#include "../include/system.h" +#include "../include/iccp_csm.h" + +/* Ethernet MAC Address setter - set by string. */ +static void ether_mac_set_addr_with_string(uint8_t* macdst, const char* macstr) +{ + char* dupmac = NULL; + char* token = NULL; + unsigned long oct; + int i = 0; + + if(macdst == NULL || macstr == NULL) + return; + + memset(macdst, 0, 6); + + dupmac = strdup(macstr); + + /* tokenize */ + token = strtok(dupmac, " -:"); + oct = strtoul(token, NULL, 16); + if(oct > 255) + oct = 0xff; + macdst[0] = oct; + + for(i=1; i<6; ++i) + { + token = strtok(NULL, " -:"); + if(token == NULL) + { + memset(macdst, 0, 6); + break; + } + oct = strtoul(token, NULL, 16); + if(oct > 255) + oct = 0xff; + macdst[i] = oct; + } + + free(dupmac); + + return; +} + +/* Get the Ethernet MAC Address by interface name. */ +void ether_mac_set_addr_with_if_name(char* name, uint8_t* mac) +{ + char addr_file[64]; + FILE *file_ptr = NULL; + char buf[64]; + + if (!mac || !name) + return; + + memset(addr_file, 0, 64); + snprintf(addr_file, 63, "/sys/class/net/%s/address", name); + + if ((file_ptr = fopen(addr_file, "r"))) + { + memset(buf, 0, 64); + fgets(buf, 63, file_ptr); + fclose(file_ptr); + ether_mac_set_addr_with_string(mac, buf); + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to find device %s from %s", name, addr_file); + } + + return; +} + +void local_if_init(struct LocalInterface* local_if) +{ + if (local_if == NULL) + return; + + memset(local_if, 0, sizeof(struct LocalInterface)); + local_if->po_id = -1; + local_if->po_active = 1; //always guess the po is active + local_if->mlacp_state = MLACP_STATE_INIT; + local_if->type = IF_T_UNKNOW; + local_if->changed = 1; + local_if->port_config_sync = 0; + local_if->is_peer_link = 0; + local_if->is_arp_accept = 0; + local_if->l3_mode = 0; + local_if->state = PORT_STATE_DOWN; + local_if->prefixlen = 32; + local_if->csm = NULL; + local_if->isolate_to_peer_link = 0; + LIST_INIT(&local_if->vlan_list); + + return; +} + +void vlan_info_init(struct VLAN_ID* vlan) +{ + vlan->vid = -1; + vlan->vlan_removed= 0; + vlan->vlan_itf = NULL; + + return; +} + +struct LocalInterface* local_if_create(int ifindex, char* ifname, int type) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + uint8_t mac[ETHER_ADDR_LEN]; + struct CSM* csm; + struct If_info * cif = NULL; + + if(!ifname) + return NULL; + + if (!(sys = system_get_instance())) + return NULL; + + if (ifindex < 0) + return NULL; + + if ((local_if = local_if_find_by_ifindex(ifindex))) + return local_if; + + if (!(local_if = (struct LocalInterface*) malloc(sizeof(struct LocalInterface)))) { + ICCPD_LOG_WARN(__FUNCTION__, "port ifindex = %d, malloc failed", ifindex); + return NULL; + } + + local_if_init(local_if); + local_if->ifindex = ifindex; + local_if->type = type; + + if(local_if->type == IF_T_PORT_CHANNEL) + { + int i; + int len; + len = strlen(ifname); + + for(i=0; i= '0' && ifname[i] <= '9') + break; + + if(i >= len) + return NULL; + + local_if->po_id = atoi(&ifname[i]); + } + + if (ifname) + snprintf(local_if->name, MAX_L_PORT_NAME, "%s", ifname); + + switch (type) + { + case IF_T_PORT_CHANNEL: + break; + case IF_T_PORT: + break; + case IF_T_VLAN: + /* do nothing currently. */ + break; + default: + ICCPD_LOG_WARN(__FUNCTION__, "the type of local interface (%s) is not acceptable", ifname); + if (local_if) + free(local_if); + return NULL; + } + + ICCPD_LOG_INFO(__FUNCTION__, + "Create a local_if = %s ifindex = %d MAC = %02x:%02x:%02x:%02x:%02x:%02x, state = %s", + ifname, local_if->ifindex, local_if->mac_addr[0], local_if->mac_addr[1], local_if->mac_addr[2], + local_if->mac_addr[3], local_if->mac_addr[4], local_if->mac_addr[5], local_if->state ? "down" : "up"); + + LIST_INSERT_HEAD(&(sys->lif_list), local_if, system_next); + + /*Check the intf is peer-link? Only support PortChannel and Ethernet currently*/ + /*When set peer-link, the local-if is probably not created*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if(strcmp(local_if->name, csm->peer_itf_name) == 0) + { + local_if->is_peer_link = 1; + csm->peer_link_if = local_if; + break; + } + /*check the intf is bind with csm*/ + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + if (strcmp(ifname, cif->name) ==0) + mlacp_bind_port_channel_to_csm(csm,ifname); + } + } + + return local_if; +} + +struct LocalInterface* local_if_find_by_name(const char* ifname) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + + if (!ifname) + return NULL; + + if (!(sys = system_get_instance())) + return NULL; + + LIST_FOREACH(local_if, &(sys->lif_list), system_next) + { + if (strcmp(local_if->name, ifname) == 0) + return local_if; + } + + return NULL; +} + +struct LocalInterface* local_if_find_by_ifindex(int ifindex) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return NULL; + + LIST_FOREACH(local_if, &(sys->lif_list), system_next) + { + if(local_if->ifindex == ifindex) + return local_if; + } + + return NULL; +} + +struct LocalInterface* local_if_find_by_po_id(int po_id) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return NULL; + + LIST_FOREACH(local_if, &(sys->lif_list), system_next) + { + if(local_if->type == IF_T_PORT_CHANNEL && local_if->po_id == po_id) + return local_if; + } + + return NULL; +} + +static void local_if_vlan_remove(struct LocalInterface *lif_vlan) +{ + struct System *sys = NULL; + struct LocalInterface *lif = NULL; + struct VLAN_ID *vlan = NULL; + + if ((sys = system_get_instance()) != NULL) + { + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if(lif_vlan != vlan->vlan_itf) + continue; + + vlan->vlan_itf = NULL; + } + } + } + + return; +} + +static void local_if_po_remove(struct LocalInterface *lif_po) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct LocalInterface *lif = NULL; + + /* remove all po member*/ + if ((sys = system_get_instance()) != NULL) + { + csm = lif_po->csm; + if (csm) + { + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type != IF_T_PORT) continue; + if (lif->po_id != lif_po->po_id) continue; + + mlacp_unbind_local_if(lif); + } + } + } + + return; +} + +static void local_if_remove(struct LocalInterface *lif) +{ + mlacp_unbind_local_if(lif); + lif->po_id = -1; + + return; +} + +void local_if_destroy(char *ifname) +{ + struct LocalInterface* lif = NULL; + struct CSM *csm = NULL; + struct System *sys = NULL; + + if (!(sys = system_get_instance())) + return; + + lif = local_if_find_by_name(ifname); + if (!lif) return; + + ICCPD_LOG_WARN(__FUNCTION__, "destroy interface %s, %d\n", lif->name, lif->ifindex); + + if (lif->type == IF_T_VLAN) + local_if_vlan_remove(lif); + else if (lif->type == IF_T_PORT_CHANNEL) + local_if_po_remove(lif); + else + local_if_remove(lif); + + csm = lif->csm; + if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + goto to_mlacp_purge; + else + goto to_sys_purge; + +to_sys_purge: + /* sys purge */ + LIST_REMOVE(lif, system_next); + if (lif->csm) LIST_REMOVE(lif, mlacp_next); + LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next); + return; + +to_mlacp_purge: + /* sys & mlacp purge */ + LIST_REMOVE(lif, system_next); + LIST_REMOVE(lif, mlacp_next); + LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next); + LIST_INSERT_HEAD(&(MLACP(csm).lif_purge_list), lif, mlacp_purge_next); + return; +} + +int local_if_is_l3_mode(struct LocalInterface* local_if) +{ + int ret = 0; + + if (local_if == NULL) + return 0; + + if (local_if->ipv4_addr !=0) + ret = 1; + + return ret; +} + +void local_if_change_flag_clear(void) +{ + struct System* sys = NULL; + struct LocalInterface* lif = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->changed == 1) + { + lif->changed = 0; + } + } + + return; +} + +void local_if_purge_clear(void) +{ + struct System* sys = NULL; + struct LocalInterface* lif = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + /* destroy purge if*/ + while (!LIST_EMPTY(&(sys->lif_purge_list))) + { + lif = LIST_FIRST(&(sys->lif_purge_list)); + ICCPD_LOG_DEBUG(__FUNCTION__, "purge %s", lif->name); + LIST_REMOVE(lif, system_purge_next); + if (lif->mlacp_purge_next.le_next!=0 && lif->mlacp_purge_next.le_prev!=0) + LIST_REMOVE(lif, mlacp_purge_next); + local_if_del_all_vlan(lif); + free(lif); + } + LIST_INIT(&(sys->lif_purge_list)); + + return; +} + +void local_if_finalize(struct LocalInterface* lif) +{ + if (lif == NULL) + return; + + local_if_del_all_vlan(lif); + + free(lif); + + return; +} + +struct PeerInterface* peer_if_create(struct CSM* csm, + int peer_if_number, int type) +{ + struct PeerInterface* peer_if = NULL; + + /* check csm*/ + if (csm == NULL) + return NULL; + + /* check id*/ + if (peer_if_number < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "peer interface id < 0"); + return NULL; + } + + /* check type*/ + if (type != IF_T_PORT && type != IF_T_PORT_CHANNEL) + { + ICCPD_LOG_WARN(__FUNCTION__, + "the type(%) of peer interface(%d) is not acceptable", + type, peer_if_number); + return NULL; + } + + /* create a new peer if*/ + if ((peer_if = (struct PeerInterface*) malloc(sizeof(struct PeerInterface))) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "peer port id = %d, malloc failed", peer_if_number); + return NULL; + } + memset(peer_if, 0, sizeof(struct PeerInterface)); + + if (type == IF_T_PORT) + { + peer_if->ifindex = peer_if_number; + peer_if->type = IF_T_PORT; + peer_if->csm = csm; + } + else if (type == IF_T_PORT_CHANNEL) + { + peer_if->ifindex = peer_if_number; + peer_if->type = IF_T_PORT_CHANNEL; + } + + LIST_INSERT_HEAD(&(MLACP(csm).pif_list), peer_if, mlacp_next); + + return peer_if; +} + +struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name) +{ + struct System* sys = NULL; + struct PeerInterface* peer_if = NULL; + + if ((sys = system_get_instance()) == NULL) + return NULL; + + if (csm == NULL) + return NULL; + + LIST_FOREACH(peer_if, &(csm->app_csm.mlacp.pif_list), mlacp_next) + { + if (strcmp(peer_if->name, name) == 0) + return peer_if; + } + + return NULL; +} + +void peer_if_del_all_vlan(struct PeerInterface* pif) +{ + struct VLAN_ID *pvlan = NULL; + + while (!LIST_EMPTY(&(pif->vlan_list))) + { + pvlan = LIST_FIRST(&(pif->vlan_list)); + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", + pvlan->vid, pif->name); + LIST_REMOVE(pvlan, port_next); + free(pvlan); + } + + return; +} + +void peer_if_destroy(struct PeerInterface* pif) +{ + ICCPD_LOG_WARN(__FUNCTION__, "destroy peer's interface %s, %d\n", + pif->name, pif->ifindex); + + /* destroy if*/ + LIST_REMOVE(pif, mlacp_next); + peer_if_del_all_vlan(pif); + + free(pif); + return; +} + +int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) +{ + struct VLAN_ID *vlan = NULL; + char vlan_name[16] = ""; + + sprintf(vlan_name, "Vlan%d", vid); + + /* traverse 1 time */ + LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) + { + if(vlan->vid == vid) + break; + } + + if (!vlan) + { + vlan = (struct VLAN_ID*) malloc(sizeof(struct VLAN_ID)); + if(!vlan) + return -1; + + ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d on %s", vid, local_if->name); + local_if->port_config_sync = 1; + LIST_INSERT_HEAD(&(local_if->vlan_list), vlan, port_next); + } + + vlan_info_init(vlan); + vlan->vid = vid; + vlan->vlan_removed = 0; + vlan->vlan_itf = local_if_find_by_name(vlan_name); + return 0; +} + +void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid) +{ + struct VLAN_ID *vlan = NULL; + + /* traverse 1 time */ + LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) + { + if(vlan->vid == vid) + break; + } + + if(vlan != NULL) + { + LIST_REMOVE(vlan, port_next); + free(vlan); + local_if->port_config_sync = 1; + } + + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d on %s", vid, local_if->name); + + return; +} + +void local_if_del_all_vlan(struct LocalInterface* lif) +{ + struct VLAN_ID* vlan = NULL; + + while (!LIST_EMPTY(&(lif->vlan_list))) + { + vlan = LIST_FIRST(&(lif->vlan_list)); + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d on %s", vlan->vid, lif->name); + LIST_REMOVE(vlan, port_next); + free(vlan); + } + + return; +} + +/* Add VLAN from peer-link*/ +int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) +{ + struct VLAN_ID *peer_vlan = NULL; + char vlan_name[16] = ""; + + sprintf(vlan_name, "Vlan%d", vlan_id); + + /* traverse 1 time */ + LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) + { + if (peer_vlan->vid == vlan_id) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "update VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); + break; + } + } + + if(!peer_vlan) + { + peer_vlan = (struct VLAN_ID*) malloc(sizeof(struct VLAN_ID)); + if(!peer_vlan) + return -1; + + ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d from peer's %s", vlan_id, peer_if->name); + LIST_INSERT_HEAD(&(peer_if->vlan_list), peer_vlan, port_next); + } + + vlan_info_init(peer_vlan); + peer_vlan->vid = vlan_id; + peer_vlan->vlan_removed = 0; + + return 0; +} + +/* Used by sync update*/ +int peer_if_clean_unused_vlan(struct PeerInterface* peer_if) +{ + struct VLAN_ID *peer_vlan = NULL; + struct VLAN_ID *peer_vlan_next = NULL; + + /* traverse 1 time */ + LIST_FOREACH(peer_vlan_next, &(peer_if->vlan_list), port_next) + { + if(peer_vlan != NULL) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); + LIST_REMOVE(peer_vlan, port_next); + free(peer_vlan); + peer_vlan = NULL; + + } + if (peer_vlan_next->vlan_removed == 1) + peer_vlan = peer_vlan_next; + } + + if(peer_vlan != NULL) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); + LIST_REMOVE(peer_vlan, port_next); + free(peer_vlan); + } + + return 0; +} + +int set_sys_arp_accept_flag(char* ifname, int flag) +{ + FILE *file_ptr = NULL; + char cmd[64]; + char arp_file[64]; + char buf[2]; + int result = -1; + + memset(arp_file, 0, 64); + snprintf(arp_file, 63, "/proc/sys/net/ipv4/conf/%s/arp_accept", ifname); + if (!(file_ptr = fopen(arp_file, "r"))) + { + ICCPD_LOG_DEBUG(__func__, "Failed to find device %s from %s", ifname, arp_file); + return result; + } + + fgets(buf, sizeof(buf), file_ptr); + if (atoi(buf) == flag) + result = 0; + else + { + memset(cmd, 0, 64); + snprintf(cmd, 63, "echo %d > /proc/sys/net/ipv4/conf/%s/arp_accept", flag, ifname); + if (system(cmd)) + ICCPD_LOG_DEBUG(__func__, "Failed to execute cmd = %s", flag, cmd); + } + + fclose(file_ptr); + return result; +} diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c new file mode 100644 index 000000000000..9c8a7b0292ab --- /dev/null +++ b/src/iccpd/src/scheduler.c @@ -0,0 +1,639 @@ +/* +* scheduler.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/logger.h" +#include "../include/system.h" +#include "../include/scheduler.h" +#include "../include/iccp_csm.h" + + +/****************************************************** + * + * Global Variable + * + ******************************************************/ + +static int session_conn_thread_lock(pthread_mutex_t *conn_mutex) +{ + return 1; /*pthread_mutex_lock(conn_mutex);*/ +} + +static int session_conn_thread_trylock(pthread_mutex_t *conn_mutex) +{ + return 0 ;/*pthread_mutex_trylock(conn_mutex);*/ +} + +static int session_conn_thread_unlock(pthread_mutex_t *conn_mutex) +{ + return 1;/* pthread_mutex_unlock(conn_mutex);*/ +} + +static void heartbeat_check(struct CSM *csm) +{ + if (csm->heartbeat_update_time == 0) + { + time(&csm->heartbeat_update_time); + return; + } + + if( (time(NULL) - csm->heartbeat_update_time) > HEARTBEAT_TIMEOUT_SEC) + { + /* hearbeat timeout*/ + ICCPD_LOG_INFO(__FUNCTION__, "iccpd connection timeout (heartbeat)"); + scheduler_session_disconnect_handler(csm); + } + + return; +} + +static void heartbeat_update(struct CSM *csm) +{ + if(csm->sock_fd > 0) + { + heartbeat_check(csm); + } + + return; +} + +/* Transit FSM of all connections */ +static int scheduler_transit_fsm() +{ + struct CSM* csm = NULL; + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return -1; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + heartbeat_update(csm); + iccp_csm_transit(csm); + app_csm_transit(csm); + mlacp_fsm_transit(csm); + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE && (time(NULL) - sys->csm_trans_time) >= 60) + { + iccp_get_fdb_change_from_syncd(); + sys->csm_trans_time = time(NULL); + } + } + + local_if_change_flag_clear(); + local_if_purge_clear(); + + return 1; +} + +/* Receive packets call back function */ +int scheduler_csm_read_callback(struct CSM* csm) +{ + struct Msg* msg = NULL; + /*peer message*/ + char *peer_msg = g_csm_buf; + LDPHdr* ldp_hdr = (LDPHdr*)peer_msg; + char* data = &peer_msg[sizeof(LDPHdr)]; + size_t data_len = 0; + size_t pos = 0; + int recv_len=0, len=0, retval; + + if (csm->sock_fd <= 0) + return -1; + + memset(peer_msg, 0, CSM_BUFFER_SIZE); + + recv_len = 0; + while(recv_len != sizeof(LDPHdr)) + { + len = recv(csm->sock_fd, peer_msg+recv_len, sizeof(LDPHdr)-recv_len, 0); + if (len == -1) + { + perror("recv(). Error"); + goto recv_err; + } + else if (len == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer disconnect"); + goto recv_err; + } + recv_len += len; + /*usleep(100);*/ + } + + data_len = ldp_hdr->msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + pos = 0; + while(data_len > 0) + { + recv_len = recv(csm->sock_fd, &data[pos], data_len, 0); + if (recv_len == -1) { + perror("continue recv(). Error"); + goto recv_err; + } + else if (recv_len == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer disconnect"); + goto recv_err; + } + data_len -= recv_len; + pos += recv_len; + /*usleep(100);*/ + } + + retval = iccp_csm_init_msg(&msg, peer_msg, ldp_hdr->msg_len + MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); + if (retval == 0) + { + iccp_csm_enqueue_msg(csm, msg); + ++csm->icc_msg_in_count; + } + else + ++csm->i_msg_in_count; + + return 1; + +recv_err: + scheduler_session_disconnect_handler(csm); + return -1; +} + +/* Handle server accept client */ +int scheduler_server_accept() +{ + int new_fd; + int ret = -1; + struct CSM* csm = NULL; + struct System* sys = NULL; + struct sockaddr_in client_addr; + socklen_t addr_len; + + if ((sys = system_get_instance()) == NULL ) + { + return -1; + } + if(sys->server_fd <= 0) + { + return -1; + } + + addr_len = sizeof(struct sockaddr_in); + new_fd = accept(sys->server_fd, (struct sockaddr *) &client_addr, &addr_len); + if (new_fd == -1) + { + goto reject_client; + } + else + { + csm = system_get_csm_by_peer_ip(inet_ntoa(client_addr.sin_addr)); + if(!csm) + { + /* can't find csm with peer ip*/ + ICCPD_LOG_INFO(__FUNCTION__, "csm null with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); + goto reject_client; + } + + if(csm->sock_fd > 0) + { + /* peer already connected*/ + ICCPD_LOG_INFO(__FUNCTION__, "csm sock is connected with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); + goto reject_client; + } + + if((ret = scheduler_check_csm_config(csm)) < 0) + { + /* csm config error*/ + ICCPD_LOG_INFO(__FUNCTION__, "csm config error with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); + goto reject_client; + } + } + + /* Accept*/ + goto accept_client; + +reject_client: + if(new_fd >= 0) close(new_fd); + return -1; + +accept_client: + session_conn_thread_lock(&csm->conn_mutex); + ICCPD_LOG_INFO(__FUNCTION__, "Server Accept, SocketFD [%d], %p", new_fd, csm); + + struct epoll_event event; + int err; + event.data.fd = new_fd; + event.events = EPOLLIN; + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, new_fd, &event); + if(err) + { + session_conn_thread_unlock(&csm->conn_mutex); + goto reject_client; + } + + csm->sock_fd = new_fd; + csm->current_state = ICCP_NONEXISTENT; + FD_SET(new_fd, &(sys->readfd)); + sys->readfd_count ++; + session_conn_thread_unlock(&csm->conn_mutex); + return 0; +} + +/* scheduler initialization */ +void scheduler_init() +{ + struct System* sys = NULL; + + if (!(sys = system_get_instance())) + return; + + /*Get kernel interface and port */ + iccp_sys_local_if_list_get_init(); + + /*Get kernel vlan info */ + iccp_get_if_vlan_info_from_netlink(); + iccp_sys_local_if_list_get_addr(); + + /*Interfaces must be created before this func called*/ + iccp_config_from_file(sys->config_file_path); + + /*Get kernel ARP info */ + iccp_arp_get_init(); + + if(iccp_connect_syncd() < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, syncd info socket connect fail", + __FUNCTION__, __LINE__); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, syncd info socket connect success", + __FUNCTION__, __LINE__); + } + + if (mclagd_ctl_sock_create() < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclagd ctl info socket connect fail", + __FUNCTION__, __LINE__); + } + + return; +} + +/* Thread fetch to call */ +void scheduler_loop() +{ + struct System* sys = NULL; + int result; + + if ((sys = system_get_instance()) == NULL) + return; + + while(1) + { + if(sys->sync_fd <= 0) + { + iccp_connect_syncd(); + } + + /*handle socket slelect event ,If no message received, it will block 0.1s*/ + iccp_handle_events(sys); + /*csm, app state machine transit */ + scheduler_transit_fsm(); + /*get netlink info again when error happens */ + iccp_netlink_sync_again(); + } + + return; +} + +/* Scheduler start while loop */ +void scheduler_start() +{ + mlacp_sync_with_kernel_callback(); + + scheduler_loop(); + + return; +} + +/* Scheduler tear down */ +void scheduler_finalize() { + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + syncd_info_close(); + + log_finalize(); + + ICCPD_LOG_INFO(__FUNCTION__, "Scheduler is terminated."); + + return; +} + +void* session_client_conn_handler(struct CSM *csm) +{ + struct System* sys = NULL; + struct sockaddr_in peer_addr; + int connFd=-1, connStat=-1; + struct timeval con_tv; + socklen_t len = sizeof(con_tv); + + /* Lock the thread*/ + session_conn_thread_lock(&csm->conn_mutex); + + sys = system_get_instance(); + if(!sys) + goto conn_fail; + + /* Create sock*/ + connFd = socket(PF_INET, SOCK_STREAM, 0); + bzero(&peer_addr, sizeof(peer_addr)); + peer_addr.sin_family = PF_INET; + peer_addr.sin_port = htons(ICCP_TCP_PORT); + peer_addr.sin_addr.s_addr = inet_addr(csm->peer_ip); + if (connFd == -1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer IP:%s Socket FD creation failed.", + csm->peer_ip); + goto conn_fail; + } + + /* Set connect timeout secs*/ + con_tv.tv_sec = 0; + con_tv.tv_usec = CONNECT_TIMEOUT_MSEC*1000; + if (setsockopt(connFd, SOL_SOCKET, SO_SNDTIMEO, &con_tv, len) == -1) + { + ICCPD_LOG_INFO(__FUNCTION__, "Set socket timeout fail"); + } + + /* Try conn*/ + ICCPD_LOG_INFO(__FUNCTION__, "Connecting. peer ip = [%s], %p", csm->peer_ip, csm); + connStat = connect(connFd, (struct sockaddr*) &(peer_addr), sizeof(peer_addr)); + ICCPD_LOG_INFO(__FUNCTION__, "Connection. fd = [%d], status = [%d], %p", + connFd, connStat, csm); + + if (connStat != 0) + { + /* Conn Fail*/ + goto conn_fail; + } + else + { + /* Conn OK*/ + struct epoll_event event; + int err; + event.data.fd = connFd; + event.events = EPOLLIN; + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, connFd, &event); + if(err) + goto conn_fail; + csm->sock_fd = connFd; + FD_SET(connFd, &(sys->readfd)); + sys->readfd_count++; + ICCPD_LOG_INFO(__FUNCTION__, "Connect to server %s sucess .", csm->peer_ip); + goto conn_ok; + } + +conn_fail: + if(connFd >= 0) + { + csm->sock_fd = -1; + close(connFd); + } +conn_ok: + time(&csm->connTimePrev); + session_conn_thread_unlock(&csm->conn_mutex); + return; +} + +/* Create socket connect to peer */ +int scheduler_prepare_session(struct CSM* csm) +{ + int ret = -1; + uint32_t local_ip = 0; + uint32_t peer_ip = 0; + + /* Init time_t*/ + if (csm->connTimePrev == 0) + { + time(&csm->connTimePrev); + } + + /* Don't conn to svr continously*/ + if((time(NULL) - csm->connTimePrev) < CONNECT_INTERVAL_SEC) + { + goto no_time_update; + } + + /* Already conn?*/ + if(csm->sock_fd > 0) + { + goto time_update; + } + + if ((ret = scheduler_check_csm_config(csm)) < 0) + goto time_update; + + /* Who is client*/ + local_ip = inet_addr(csm->sender_ip); + peer_ip = inet_addr(csm->peer_ip); + if(local_ip > peer_ip) + { + goto time_update; + } + else if(local_ip == peer_ip) + { + ICCPD_LOG_WARN("connect", + "Sender IP is as the same as the peer IP. " + "This must be fixed before connection is built."); + goto time_update; + } + + if(session_conn_thread_trylock(&csm->conn_mutex) == 0) + { + session_client_conn_handler(csm); + session_conn_thread_unlock(&csm->conn_mutex); + } + +time_update: + time(&csm->connTimePrev); + return 0; + +no_time_update: + return 0; +} + +/* Server socket initialization */ +void scheduler_server_sock_init() +{ + int optval = 1; + struct System* sys = NULL; + struct sockaddr_in svr_addr; + + if ((sys = system_get_instance()) == NULL) + return; + + sys->server_fd = socket(PF_INET, SOCK_STREAM, 0); + bzero(&(svr_addr), sizeof(svr_addr)); + svr_addr.sin_family = PF_INET; + svr_addr.sin_port = htons(ICCP_TCP_PORT); + svr_addr.sin_addr.s_addr = INADDR_ANY; + + if (sys->server_fd == -1) + { + ICCPD_LOG_ERR(__FUNCTION__, "Server Socket FD creation failed."); + return; + } + + if (setsockopt(sys->server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) + { + ICCPD_LOG_INFO(__FUNCTION__,"Set socket option failed. Error"); + /*return;*/ + } + + /* set_nonblocking(sys->server_fd);*/ + + if (bind(sys->server_fd, (struct sockaddr*) &(svr_addr), sizeof(svr_addr)) < 0) + { + ICCPD_LOG_INFO(__FUNCTION__,"Bind socket failed. Error"); + return; + } + + if (listen(sys->server_fd, MAX_ACCEPT_CONNETIONS) == -1) + { + ICCPD_LOG_INFO(__FUNCTION__,"Listen failed. Error"); + return; + } + + ICCPD_LOG_INFO(__FUNCTION__, "Server socket init done."); + + return; +} + +int iccp_get_server_sock_fd() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return 0; + + return sys->server_fd; +} + +/* Server socket initialization */ +int scheduler_check_csm_config(struct CSM* csm) +{ + int ret = 1; + struct LocalInterface* lif = NULL; + struct System* sys = NULL; + + if((sys = system_get_instance()) == NULL) + return -1; + + if (csm == NULL ) + return -1; + + if(csm->mlag_id <= 0) + ret = -1; + else if (strlen(csm->peer_itf_name) <= 0) + ret = -1; + else if (strlen(csm->peer_ip) <= 0) + ret = -1; + else if (strlen(csm->sender_ip) <= 0) + ret = -1; + else if ((lif=local_if_find_by_name(csm->peer_itf_name)) == NULL) + ret = -1; + else + { + lif->is_peer_link = 1; + csm->peer_link_if = lif; + } + + if(ret == -1) + ICCPD_LOG_INFO(__FUNCTION__, "mclag config is not complete or conflicting, please check!"); + /* Decide STP role*/ + iccp_csm_stp_role_count(csm); + + return ret; +} + +int scheduler_unregister_sock_read_event_callback(struct CSM* csm) +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL ) + return -1; + + if (csm == NULL ) + { + return -2; + } + + FD_CLR(csm->sock_fd, &(sys->readfd)); + + return 0; +} + +void scheduler_session_disconnect_handler(struct CSM* csm) +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL ) + return ; + + struct epoll_event event; + + if (csm == NULL) + return ; + + session_conn_thread_lock(&csm->conn_mutex); + scheduler_unregister_sock_read_event_callback(csm); + if(csm->sock_fd > 0) + { + event.data.fd = csm->sock_fd; + event.events = EPOLLIN; + epoll_ctl(sys->epoll_fd, EPOLL_CTL_DEL, csm->sock_fd, &event); + + close(csm->sock_fd); + csm->sock_fd = -1; + } + + mlacp_peerlink_disconn_handler(csm); + MLACP(csm).current_state = MLACP_STATE_INIT; + iccp_csm_status_reset(csm, 0); + time(&csm->connTimePrev); + session_conn_thread_unlock(&csm->conn_mutex); + + return; +} diff --git a/src/iccpd/src/system.c b/src/iccpd/src/system.c new file mode 100644 index 000000000000..1f30d4ae20a0 --- /dev/null +++ b/src/iccpd/src/system.c @@ -0,0 +1,185 @@ +/* +* system.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include + +#include "../include/iccp_csm.h" +#include "../include/logger.h" +#include "../include/iccp_netlink.h" + +/* Singleton */ +struct System* system_get_instance() +{ + static struct System* sys = NULL; + + if (sys == NULL ) + { + sys = (struct System*) malloc(sizeof(struct System)); + if (sys == NULL ) + { + return NULL ; + } + system_init(sys); + } + + return sys; +} + +/* System instance initialization */ +void system_init(struct System* sys) +{ + if (sys == NULL ) + return; + + sys->server_fd = -1; + sys->sync_fd = -1; + sys->sync_ctrl_fd = -1; + sys->arp_receive_fd = -1; + sys->epoll_fd = -1; + LIST_INIT(&(sys->csm_list)); + LIST_INIT(&(sys->lif_list)); + LIST_INIT(&(sys->lif_purge_list)); + + sys->log_file_path = strdup("/var/log/iccpd.log"); + sys->cmd_file_path = strdup("/var/run/iccpd/iccpd.vty"); + sys->config_file_path = strdup("/etc/iccpd/iccpd.conf"); + sys->mclagdctl_file_path = strdup("/var/run/iccpd/mclagdctl.sock"); + sys->pid_file_fd = 0; + sys->telnet_port = 2015; + FD_ZERO(&(sys->readfd)); + sys->readfd_count = 0; + sys->csm_trans_time = 0; + sys->need_sync_team_again = 0; + sys->need_sync_netlink_again = 0; + scheduler_server_sock_init(); + iccp_system_init_netlink_socket(); + iccp_init_netlink_event_fd(sys); +} + +/* System instance tear down */ +void system_finalize() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + + if ((sys = system_get_instance()) == NULL ) + return; + + ICCPD_LOG_INFO(__FUNCTION__, "System resource pool is destructing."); + + while (!LIST_EMPTY(&(sys->csm_list))) + { + csm = LIST_FIRST(&(sys->csm_list)); + iccp_csm_finalize(csm); + } + + /* Release all port objects */ + while (!LIST_EMPTY(&(sys->lif_list))) + { + local_if = LIST_FIRST(&(sys->lif_list)); + local_if_finalize(local_if); + } + while (!LIST_EMPTY(&(sys->lif_purge_list))) + { + local_if = LIST_FIRST(&(sys->lif_list)); + local_if_finalize(local_if); + } + + if (sys->log_file_path != NULL ) + free(sys->log_file_path); + if (sys->cmd_file_path != NULL ) + free(sys->cmd_file_path); + if (sys->config_file_path != NULL ) + free(sys->config_file_path); + if (sys->pid_file_fd > 0) + close(sys->pid_file_fd); + if(sys->server_fd > 0) + close(sys->server_fd); + if(sys->sync_fd > 0) + close(sys->sync_fd); + if(sys->sync_ctrl_fd > 0) + close(sys->sync_ctrl_fd); + if(sys->arp_receive_fd > 0) + close(sys->arp_receive_fd); + if(sys->epoll_fd) + close(sys->epoll_fd); + + free(sys); + ICCPD_LOG_INFO(__FUNCTION__, "System resource pool destructed successfully..."); +} + +struct CSM* system_create_csm() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return NULL ; + + /* Create a new csm */ + csm = (struct CSM*) malloc(sizeof(struct CSM)); + if (csm == NULL ) + return NULL; + else + memset(csm, 0, sizeof(struct CSM)); + iccp_csm_init(csm); + LIST_INSERT_HEAD(&(sys->csm_list), csm, next); + + return csm; +} + +/* Get connect state machine instance by peer ip */ +struct CSM* system_get_csm_by_peer_ip(const char* peer_ip) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return NULL ; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (strcmp(csm->peer_ip, peer_ip) == 0) + return csm; + } + + return NULL ; +} + +struct CSM* system_get_csm_by_mlacp_id(int id) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return NULL ; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm->app_csm.mlacp.id == id) + return csm; + } + + return NULL ; +} From d99e9d69663a3ef1012f0538ecde1c075fa068ed Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 31 Jan 2019 23:02:51 -0800 Subject: [PATCH 02/23] MCLAG feature for sonic --- dockers/docker-iccpd/Dockerfile | 30 + dockers/docker-iccpd/Dockerfile.j2 | 35 + .../docker-iccpd/base_image_files/mclagdctl | 10 + dockers/docker-iccpd/iccpd.j2 | 8 + dockers/docker-iccpd/iccpd.sh | 17 + dockers/docker-iccpd/start.sh | 18 + dockers/docker-iccpd/supervisord.conf | 29 + files/build_templates/docker_image_ctl.j2 | 3 + files/build_templates/iccpd.service.j2 | 13 + rules/docker-iccpd.mk | 14 + rules/iccpd.mk | 13 + src/iccpd/Makefile | 33 + src/iccpd/debian/DEBIAN/control | 12 + src/iccpd/include/app_csm.h | 71 + src/iccpd/include/cmd_option.h | 82 + src/iccpd/include/iccp_cli.h | 55 + src/iccpd/include/iccp_cmd.h | 27 + src/iccpd/include/iccp_cmd_show.h | 35 + src/iccpd/include/iccp_consistency_check.h | 42 + src/iccpd/include/iccp_csm.h | 162 ++ src/iccpd/include/iccp_ifm.h | 42 + src/iccpd/include/iccp_netlink.h | 44 + src/iccpd/include/logger.h | 67 + src/iccpd/include/mlacp_fsm.h | 102 + src/iccpd/include/mlacp_link_handler.h | 51 + src/iccpd/include/mlacp_sync_prepare.h | 54 + src/iccpd/include/mlacp_sync_update.h | 45 + src/iccpd/include/mlacp_tlv.h | 413 ++++ src/iccpd/include/msg_format.h | 427 ++++ src/iccpd/include/port.h | 149 ++ src/iccpd/include/scheduler.h | 58 + src/iccpd/include/system.h | 83 + src/iccpd/src/Makefile | 55 + src/iccpd/src/app_csm.c | 312 +++ src/iccpd/src/cmd_option.c | 262 +++ src/iccpd/src/iccp_cli.c | 363 ++++ src/iccpd/src/iccp_cmd.c | 160 ++ src/iccpd/src/iccp_cmd_show.c | 474 +++++ src/iccpd/src/iccp_consistency_check.c | 175 ++ src/iccpd/src/iccp_csm.c | 746 +++++++ src/iccpd/src/iccp_ifm.c | 1037 ++++++++++ src/iccpd/src/iccp_main.c | 186 ++ src/iccpd/src/iccp_netlink.c | 1136 +++++++++++ src/iccpd/src/logger.c | 124 ++ src/iccpd/src/mclagdctl/Makefile | 28 + src/iccpd/src/mclagdctl/mclagdctl.c | 792 ++++++++ src/iccpd/src/mclagdctl/mclagdctl.h | 177 ++ src/iccpd/src/mclagdctl/mclagdctl.o | Bin 0 -> 86776 bytes src/iccpd/src/mlacp_fsm.c | 1136 +++++++++++ src/iccpd/src/mlacp_link_handler.c | 1789 +++++++++++++++++ src/iccpd/src/mlacp_sync_prepare.c | 789 ++++++++ src/iccpd/src/mlacp_sync_update.c | 741 +++++++ src/iccpd/src/port.c | 711 +++++++ src/iccpd/src/scheduler.c | 639 ++++++ src/iccpd/src/system.c | 185 ++ 55 files changed, 14261 insertions(+) create mode 100644 dockers/docker-iccpd/Dockerfile create mode 100644 dockers/docker-iccpd/Dockerfile.j2 create mode 100644 dockers/docker-iccpd/base_image_files/mclagdctl create mode 100644 dockers/docker-iccpd/iccpd.j2 create mode 100644 dockers/docker-iccpd/iccpd.sh create mode 100644 dockers/docker-iccpd/start.sh create mode 100644 dockers/docker-iccpd/supervisord.conf create mode 100644 files/build_templates/iccpd.service.j2 create mode 100644 rules/docker-iccpd.mk create mode 100644 rules/iccpd.mk create mode 100644 src/iccpd/Makefile create mode 100644 src/iccpd/debian/DEBIAN/control create mode 100644 src/iccpd/include/app_csm.h create mode 100644 src/iccpd/include/cmd_option.h create mode 100644 src/iccpd/include/iccp_cli.h create mode 100644 src/iccpd/include/iccp_cmd.h create mode 100644 src/iccpd/include/iccp_cmd_show.h create mode 100644 src/iccpd/include/iccp_consistency_check.h create mode 100644 src/iccpd/include/iccp_csm.h create mode 100644 src/iccpd/include/iccp_ifm.h create mode 100644 src/iccpd/include/iccp_netlink.h create mode 100644 src/iccpd/include/logger.h create mode 100644 src/iccpd/include/mlacp_fsm.h create mode 100644 src/iccpd/include/mlacp_link_handler.h create mode 100644 src/iccpd/include/mlacp_sync_prepare.h create mode 100644 src/iccpd/include/mlacp_sync_update.h create mode 100644 src/iccpd/include/mlacp_tlv.h create mode 100644 src/iccpd/include/msg_format.h create mode 100644 src/iccpd/include/port.h create mode 100644 src/iccpd/include/scheduler.h create mode 100644 src/iccpd/include/system.h create mode 100644 src/iccpd/src/Makefile create mode 100644 src/iccpd/src/app_csm.c create mode 100644 src/iccpd/src/cmd_option.c create mode 100644 src/iccpd/src/iccp_cli.c create mode 100644 src/iccpd/src/iccp_cmd.c create mode 100644 src/iccpd/src/iccp_cmd_show.c create mode 100644 src/iccpd/src/iccp_consistency_check.c create mode 100644 src/iccpd/src/iccp_csm.c create mode 100644 src/iccpd/src/iccp_ifm.c create mode 100644 src/iccpd/src/iccp_main.c create mode 100644 src/iccpd/src/iccp_netlink.c create mode 100644 src/iccpd/src/logger.c create mode 100644 src/iccpd/src/mclagdctl/Makefile create mode 100644 src/iccpd/src/mclagdctl/mclagdctl.c create mode 100644 src/iccpd/src/mclagdctl/mclagdctl.h create mode 100644 src/iccpd/src/mclagdctl/mclagdctl.o create mode 100644 src/iccpd/src/mlacp_fsm.c create mode 100644 src/iccpd/src/mlacp_link_handler.c create mode 100644 src/iccpd/src/mlacp_sync_prepare.c create mode 100644 src/iccpd/src/mlacp_sync_update.c create mode 100644 src/iccpd/src/port.c create mode 100644 src/iccpd/src/scheduler.c create mode 100644 src/iccpd/src/system.c diff --git a/dockers/docker-iccpd/Dockerfile b/dockers/docker-iccpd/Dockerfile new file mode 100644 index 000000000000..d932ff955561 --- /dev/null +++ b/dockers/docker-iccpd/Dockerfile @@ -0,0 +1,30 @@ +FROM docker-config-engine + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +RUN apt-get install -f -y libdbus-1-3 libdaemon0 libjansson4 + +## Install redis-tools dependencies +## TODO: implicitly install dependencies +RUN apt-get -y install libjemalloc1 +RUN apt-get -y install libpython2.7 +RUN apt-get -y install ebtables +RUN apt-get install -f kmod + +COPY \ +debs/libnl-3-200_3.2.27-2_amd64.deb debs/libnl-route-3-200_3.2.27-2_amd64.deb debs/libnl-genl-3-200_3.2.27-2_amd64.deb debs/libnl-nf-3-200_3.2.27-2_amd64.deb debs/libhiredis0.13_0.13.3-2_amd64.deb debs/libnl-cli-3-200_3.2.27-2_amd64.deb debs/libswsscommon_1.0.0_amd64.deb debs/libsairedis_1.0.0_amd64.deb debs/libsaimetadata_1.0.0_amd64.deb debs/libteam5_1.26-1_amd64.deb debs/python-swsscommon_1.0.0_amd64.deb debs/swss_1.0.0_amd64.deb debs/redis-tools_3.2.4-1~bpo8+1_amd64.deb debs/iccpd_0.0.5_amd64.deb debs/ + +RUN dpkg -i \ +debs/libnl-3-200_3.2.27-2_amd64.deb debs/libnl-route-3-200_3.2.27-2_amd64.deb debs/libnl-genl-3-200_3.2.27-2_amd64.deb debs/libnl-nf-3-200_3.2.27-2_amd64.deb debs/libhiredis0.13_0.13.3-2_amd64.deb debs/libnl-cli-3-200_3.2.27-2_amd64.deb debs/libswsscommon_1.0.0_amd64.deb debs/libsairedis_1.0.0_amd64.deb debs/libsaimetadata_1.0.0_amd64.deb debs/libteam5_1.26-1_amd64.deb debs/python-swsscommon_1.0.0_amd64.deb debs/swss_1.0.0_amd64.deb debs/redis-tools_3.2.4-1~bpo8+1_amd64.deb debs/iccpd_0.0.5_amd64.deb + +COPY ["start.sh", "iccpd.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["iccpd.j2", "/usr/share/sonic/templates/"] + +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] \ No newline at end of file diff --git a/dockers/docker-iccpd/Dockerfile.j2 b/dockers/docker-iccpd/Dockerfile.j2 new file mode 100644 index 000000000000..7f09c6b8ccd3 --- /dev/null +++ b/dockers/docker-iccpd/Dockerfile.j2 @@ -0,0 +1,35 @@ +FROM docker-config-engine + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +RUN apt-get install -f -y libdbus-1-3 libdaemon0 libjansson4 + +## Install redis-tools dependencies +## TODO: implicitly install dependencies +RUN apt-get -y install libjemalloc1 +RUN apt-get -y install libpython2.7 +RUN apt-get -y install ebtables +RUN apt-get install -f kmod + +COPY \ +{% for deb in docker_iccpd_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN dpkg -i \ +{% for deb in docker_iccpd_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "iccpd.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["iccpd.j2", "/usr/share/sonic/templates/"] + +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-iccpd/base_image_files/mclagdctl b/dockers/docker-iccpd/base_image_files/mclagdctl new file mode 100644 index 000000000000..7c0b45dd0625 --- /dev/null +++ b/dockers/docker-iccpd/base_image_files/mclagdctl @@ -0,0 +1,10 @@ +#!/bin/bash + +DOCKER_EXEC_FLAGS="i" + +# Determine whether stdout is on a terminal +if [ -t 1 ] ; then + DOCKER_EXEC_FLAGS+="t" +fi + +docker exec -$DOCKER_EXEC_FLAGS iccpd mclagdctl "$@" diff --git a/dockers/docker-iccpd/iccpd.j2 b/dockers/docker-iccpd/iccpd.j2 new file mode 100644 index 000000000000..c4e6e26b10c0 --- /dev/null +++ b/dockers/docker-iccpd/iccpd.j2 @@ -0,0 +1,8 @@ +{% for mclag_id in MC_LAG %} +mclag_id:{{mclag_id}} + local_ip:{{MC_LAG[mclag_id]['local_ip']}} + peer_ip:{{MC_LAG[mclag_id]['peer_ip']}} + peer_link:{{MC_LAG[mclag_id]['peer_link']}} + bind_lacp:{{MC_LAG[mclag_id]['bind_lacp']}} +{% endfor %} + diff --git a/dockers/docker-iccpd/iccpd.sh b/dockers/docker-iccpd/iccpd.sh new file mode 100644 index 000000000000..d3b2888344ac --- /dev/null +++ b/dockers/docker-iccpd/iccpd.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +function start_app { + rm -f /var/run/iccpd/* + mclagsyncd & + iccpd +} + +function clean_up { + pkill -9 mclagsyncd + pkill -9 iccpd + exit +} + +trap clean_up SIGTERM SIGKILL +start_app +read diff --git a/dockers/docker-iccpd/start.sh b/dockers/docker-iccpd/start.sh new file mode 100644 index 000000000000..d17634cb836a --- /dev/null +++ b/dockers/docker-iccpd/start.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + + +ICCPD_CONF_PATH=/etc/iccpd + +rm -rf $ICCPD_CONF_PATH +mkdir -p $ICCPD_CONF_PATH + +sonic-cfggen -d -t /usr/share/sonic/templates/iccpd.j2 > $ICCPD_CONF_PATH/iccpd.conf + +mkdir -p /var/sonic +echo "# Config files managed by sonic-config-engine" > /var/sonic/config_status + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start iccpd diff --git a/dockers/docker-iccpd/supervisord.conf b/dockers/docker-iccpd/supervisord.conf new file mode 100644 index 000000000000..dc71f07c6c30 --- /dev/null +++ b/dockers/docker-iccpd/supervisord.conf @@ -0,0 +1,29 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:iccpd] +command=/usr/bin/iccpd.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2 index a3cbf5adbae7..df24f9c95bc3 100644 --- a/files/build_templates/docker_image_ctl.j2 +++ b/files/build_templates/docker_image_ctl.j2 @@ -137,6 +137,9 @@ start() { -v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \ {%- if docker_container_name != "database" %} -v /usr/share/sonic/device/$PLATFORM/$HWSKU:/usr/share/sonic/hwsku:ro \ +{%- endif %} +{%- if docker_container_name == "iccpd" %} + -v /lib/modules:/lib/modules:ro \ {%- endif %} --tmpfs /tmp \ --tmpfs /var/tmp \ diff --git a/files/build_templates/iccpd.service.j2 b/files/build_templates/iccpd.service.j2 new file mode 100644 index 000000000000..17017ef1549e --- /dev/null +++ b/files/build_templates/iccpd.service.j2 @@ -0,0 +1,13 @@ +[Unit] +Description=ICCPD container +Requires=updategraph.service swss.service teamd.service +After=updategraph.service swss.service teamd.service + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start +ExecStart=/usr/bin/{{docker_container_name}}.sh attach +ExecStop=/usr/bin/{{docker_container_name}}.sh stop + +[Install] +WantedBy=multi-user.target diff --git a/rules/docker-iccpd.mk b/rules/docker-iccpd.mk new file mode 100644 index 000000000000..c15e95694ba0 --- /dev/null +++ b/rules/docker-iccpd.mk @@ -0,0 +1,14 @@ +# docker image for iccpd agent + +DOCKER_ICCPD = docker-iccpd.gz +$(DOCKER_ICCPD)_PATH = $(DOCKERS_PATH)/docker-iccpd +$(DOCKER_ICCPD)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(ICCPD) +$(DOCKER_ICCPD)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +SONIC_DOCKER_IMAGES += $(DOCKER_ICCPD) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ICCPD) + +$(DOCKER_ICCPD)_CONTAINER_NAME = iccpd +$(DOCKER_ICCPD)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ICCPD)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro + +$(DOCKER_ICCPD)_BASE_IMAGE_FILES += mclagdctl:/usr/bin/mclagdctl diff --git a/rules/iccpd.mk b/rules/iccpd.mk new file mode 100644 index 000000000000..1923a9a2a62d --- /dev/null +++ b/rules/iccpd.mk @@ -0,0 +1,13 @@ +# iccpd package + +ICCPD_VERSION = 0.0.5 + +ICCPD = iccpd_$(ICCPD_VERSION)_amd64.deb +$(ICCPD)_DEPENDS += $(LIBNL_GENL3_DEV) $(LIBNL_CLI_DEV) +$(ICCPD)_RDEPENDS += $(LIBNL_GENL3) $(LIBNL_CLI) +$(ICCPD)_SRC_PATH = $(SRC_PATH)/iccpd +SONIC_MAKE_DEBS += $(ICCPD) + +# Export these variables so they can be used in a sub-make +export ICCPD_VERSION +export ICCPD diff --git a/src/iccpd/Makefile b/src/iccpd/Makefile new file mode 100644 index 000000000000..5dbbd8b89bd0 --- /dev/null +++ b/src/iccpd/Makefile @@ -0,0 +1,33 @@ +.ONESHELL: +SHELL = /bin/bash +.SHELLFLAGS += -e + +MAIN_TARGET = iccpd_$(ICCPD_VERSION)_amd64.deb +DEB_PATH = debian + +all: iccpd-build mclagdctl-build + +iccpd-build: + make -C src + +mclagdctl-build: + make -C src/mclagdctl + +$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : + make all + if [ ! -d $(DEB_PATH)/usr/bin ]; then + mkdir -p $(DEB_PATH)/usr/bin + fi + cp iccpd $(DEB_PATH)/usr/bin/iccpd + cp src/mclagdctl/mclagdctl $(DEB_PATH)/usr/bin/mclagdctl + md5sum $(DEB_PATH)/usr/bin/iccpd > $(DEB_PATH)/DEBIAN/md5sums + md5sum $(DEB_PATH)/usr/bin/mclagdctl >> $(DEB_PATH)/DEBIAN/md5sums + dpkg-deb -b $(DEB_PATH) $(DEST)/$(MAIN_TARGET) + +clean: iccpd-clean mclagdctl-clean + +iccpd-clean: + make -C src clean + +mclagdctl-clean: + make -C src/mclagdctl clean diff --git a/src/iccpd/debian/DEBIAN/control b/src/iccpd/debian/DEBIAN/control new file mode 100644 index 000000000000..cedfa03f37c0 --- /dev/null +++ b/src/iccpd/debian/DEBIAN/control @@ -0,0 +1,12 @@ +Package: iccpd-0.0.5-amd64 +Source: nps +Version: 0.0.5 +Architecture: amd64 +Maintainer: Simon Ji +Installed-Size: 1508 +Depends: +Section: main +Priority: extra +Homepage: https://github.com/NephosInc/SONiC +Description: + diff --git a/src/iccpd/include/app_csm.h b/src/iccpd/include/app_csm.h new file mode 100644 index 000000000000..6a5e554bc73e --- /dev/null +++ b/src/iccpd/include/app_csm.h @@ -0,0 +1,71 @@ +/* +* app_csm.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef APP_CSM_H_ +#define APP_CSM_H_ + +#include + +#include "../include/mlacp_fsm.h" + +struct CSM; + +enum APP_CONNECTION_STATE { + APP_NONEXISTENT, + APP_RESET, + APP_CONNSENT, + APP_CONNREC, + APP_CONNECTING, + APP_OPERATIONAL +}; + +typedef enum APP_CONNECTION_STATE APP_CONNECTION_STATE_E; + +struct AppCSM { + struct mLACP mlacp; + APP_CONNECTION_STATE_E current_state; + + uint32_t rx_connect_msg_id; + uint32_t tx_connect_msg_id; + uint32_t invalid_msg_id; + + TAILQ_HEAD(app_msg_list, Msg) app_msg_list; + + uint8_t invalid_msg :1; + uint8_t nak_msg :1; +}; + +void app_csm_init(struct CSM*, int all); +void app_csm_finalize(struct CSM*); +void app_csm_transit(struct CSM*); +int app_csm_prepare_iccp_msg(struct CSM*, char*, size_t); +void app_csm_enqueue_msg(struct CSM*, struct Msg*); +struct Msg* app_csm_dequeue_msg(struct CSM*); +void app_csm_correspond_from_msg(struct CSM*, struct Msg*); +void app_csm_correspond_from_connect_msg(struct CSM*, struct Msg*); +void app_csm_correspond_from_connect_ack_msg(struct CSM*, struct Msg*); +int app_csm_prepare_nak_msg(struct CSM*, char*, size_t); +int app_csm_prepare_connect_msg(struct CSM*, char*, size_t); +int app_csm_prepare_connect_ack_msg(struct CSM*, char*, size_t); + +#endif /* APP_CSM_H_ */ diff --git a/src/iccpd/include/cmd_option.h b/src/iccpd/include/cmd_option.h new file mode 100644 index 000000000000..d81249ea5e93 --- /dev/null +++ b/src/iccpd/include/cmd_option.h @@ -0,0 +1,82 @@ +/* +* cmd_option.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef CMD_OPTION_H_ +#define CMD_OPTION_H_ + +#include +#include +#include +#include +#include +#include + +#define OPTION_MAX_LEN 256 +#define MSG_LEN 81 + +#define CMD_OPTION_PARSER_INIT_VALUE \ +{ \ + .log_file_path = "/var/log/iccpd.log", \ + .pid_file_path = "/var/run/iccpd/iccpd.pid", \ + .cmd_file_path = "/var/run/iccpd/iccpd.vty", \ + .config_file_path = "/etc/iccpd/iccpd.conf", \ + .mclagdctl_file_path = "/var/run/iccpd/mclagdctl.sock", \ + .console_log = 0, \ + .telnet_port = 2015, \ + .init = cmd_option_parser_init, \ + .finalize = cmd_option_parser_finalize, \ + .dump_usage = cmd_option_parser_dump_usage, \ + .parse = cmd_option_parser_parse, \ +} + +struct CmdOption { + char* desc; + char* option; + char* parameter; + LIST_ENTRY(CmdOption) next; +}; + +struct CmdOptionParser { + char* log_file_path; + char* pid_file_path; + char* cmd_file_path; + char* config_file_path; + char *mclagdctl_file_path; + uint8_t console_log; + uint16_t telnet_port; + LIST_HEAD(option_list, CmdOption) option_list; + int (*parse)(struct CmdOptionParser*, int, char*[]); + void (*init)(struct CmdOptionParser*); + void (*finalize)(struct CmdOptionParser*); + void (*dump_usage)(struct CmdOptionParser*, char*); +}; + +int cmd_option_parser_parse(struct CmdOptionParser*, int, char*[]); +struct CmdOption* cmd_option_add(struct CmdOptionParser*, char*); +struct CmdOption* cmd_option_find(struct CmdOptionParser*, char*); +void cmd_option_delete(struct CmdOption*); +void cmd_option_parser_init(struct CmdOptionParser*); +void cmd_option_parser_finalize(struct CmdOptionParser*); +void cmd_option_parser_dump_usage(struct CmdOptionParser*, char*); + +#endif /* CMD_OPTION_H_ */ diff --git a/src/iccpd/include/iccp_cli.h b/src/iccpd/include/iccp_cli.h new file mode 100644 index 000000000000..1c504ed12940 --- /dev/null +++ b/src/iccpd/include/iccp_cli.h @@ -0,0 +1,55 @@ +/* +* iccp_cli.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef _ICCP_CLI_H +#define _ICCP_CLI_H + +#include + +struct CSM; + +typedef enum { + QU_TYPE_NONE, + QU_TYPE_MLAG_ADD_PO +} cli_queue_type_et; + +typedef struct cli_param_queue { + char ifname[16]; + cli_queue_type_et type; + int param; + int itf_add; + LIST_ENTRY(cli_param_queue) cli_queue_next; +} cli_param_queue_st; + +int set_mc_lag_id(struct CSM* csm, uint16_t domain); +int set_peer_link(int mid, const char* ifname); +int set_local_address(int mid, const char* addr); +int set_peer_address(int mid, const char* addr); +int unset_mc_lag_id(struct CSM* csm, uint16_t domain); +int unset_peer_link(int mid); +int unset_local_address(int mid); +int unset_peer_address(int mid); + +int iccp_cli_attach_mclag_domain_to_port_channel(int domain, const char* ifname); +int iccp_cli_detach_mclag_domain_to_port_channel(const char* ifname); +#endif diff --git a/src/iccpd/include/iccp_cmd.h b/src/iccpd/include/iccp_cmd.h new file mode 100644 index 000000000000..a37a90661ea5 --- /dev/null +++ b/src/iccpd/include/iccp_cmd.h @@ -0,0 +1,27 @@ +/* +* iccp_cmd.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef ICCP_CMD_H_ +#define ICCP_CMD_H_ + +#endif /* ICCP_CMD_H_ */ diff --git a/src/iccpd/include/iccp_cmd_show.h b/src/iccpd/include/iccp_cmd_show.h new file mode 100644 index 000000000000..4d3238f95a48 --- /dev/null +++ b/src/iccpd/include/iccp_cmd_show.h @@ -0,0 +1,35 @@ +/* +* iccp_cmd_show.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef _ICCP_CMD_SHOW_H +#define _ICCP_CMD_SHOW_H + +#define ICCP_MAX_PORT_NAME 20 +#define ICCP_MAX_IP_STR_LEN 16 + +extern int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) ; +extern int iccp_arp_dump(char * *buf, int *num, int mclag_id); +extern int iccp_mac_dump(char * *buf, int *num, int mclag_id); +extern int iccp_local_if_dump(char * *buf, int *num,int mclag_id); +extern int iccp_peer_if_dump(char * *buf, int *num, int mclag_id); +#endif diff --git a/src/iccpd/include/iccp_consistency_check.h b/src/iccpd/include/iccp_consistency_check.h new file mode 100644 index 000000000000..e6fe51f364c5 --- /dev/null +++ b/src/iccpd/include/iccp_consistency_check.h @@ -0,0 +1,42 @@ +/* +* iccp_consistency_check.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +* +*/ + +#ifndef _ICCP_CONSISTENCY_CHECK_H +#define _ICCP_CONSISTENCY_CHECK_H + + +enum Reason_ID { + REASON_NONE = 0, + REASON_INTERRFACE_MODE_IS_ASYNC, + REASON_PEER_IF_IP_IS_ASYNC, + REASON_PEER_IF_VLAN_IS_ASYNC, + REASON_MAX_ARRAY_SIZE +}; + +extern const char *reasons[]; + +enum Reason_ID iccp_consistency_check(char* ifname); + + +#endif diff --git a/src/iccpd/include/iccp_csm.h b/src/iccpd/include/iccp_csm.h new file mode 100644 index 000000000000..e57370f3ddd7 --- /dev/null +++ b/src/iccpd/include/iccp_csm.h @@ -0,0 +1,162 @@ +/* +* iccp_csm.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef ICCP_CSM_H_ +#define ICCP_CSM_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "../include/app_csm.h" +#include "../include/msg_format.h" +#include "../include/port.h" + +#define CSM_BUFFER_SIZE 65536 + +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif /*IFNAMSIZ*/ + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif /* INET_ADDRSTRLEN */ + +/* For socket binding */ +#define ICCP_TCP_PORT 8888 +#define MAX_ACCEPT_CONNETIONS 20 + +/* LDP message ID */ +extern uint32_t ICCP_MSG_ID; + +/* Global Buffer */ +extern char g_csm_buf[CSM_BUFFER_SIZE]; + +struct IccpInfo { + uint32_t icc_rg_id; + char sender_name[MAX_L_ICC_SENDER_NAME]; + uint32_t status_code; + uint8_t peer_capability_flag :1; + uint8_t peer_rg_connect_flag :1; + uint8_t sender_capability_flag :1; + uint8_t sender_rg_connect_flag :1; + uint32_t rejected_msg_id; +}; + +/* Receive message node */ +struct Msg { + char* buf; + size_t len; + TAILQ_ENTRY(Msg) tail; +}; + +/* Connection state */ +enum ICCP_CONNECTION_STATE { + ICCP_NONEXISTENT, + ICCP_INITIALIZED, + ICCP_CAPSENT, + ICCP_CAPREC, + ICCP_CONNECTING, + ICCP_OPERATIONAL +}; + +typedef enum ICCP_CONNECTION_STATE ICCP_CONNECTION_STATE_E; + +typedef enum stp_role_type_e { + STP_ROLE_NONE, /* mstp do nothing*/ + STP_ROLE_ACTIVE, /* mstp report port state*/ + STP_ROLE_STANDBY /* mstp fwd bpdu & set port state*/ +} stp_role_type_et; + +/* Connection state machine instance */ +struct CSM { + int mlag_id; + + /* Socket info */ + int sock_fd; + pthread_mutex_t conn_mutex; + time_t connTimePrev; + time_t heartbeat_send_time; + time_t heartbeat_update_time; + char peer_itf_name[IFNAMSIZ]; + char peer_ip[INET_ADDRSTRLEN]; + char sender_ip[INET_ADDRSTRLEN]; + void* sock_read_event_ptr; + + /* Msg queue */ + TAILQ_HEAD(msg_list, Msg) msg_list; + + /* System ID */ + time_t sysid_update_time; + time_t isolate_update_time; + + /* STP role */ + stp_role_type_et role_type; + + /* Peers msg */ + struct LocalInterface* peer_link_if; + struct IccpInfo iccp_info; + struct AppCSM app_csm; + ICCP_CONNECTION_STATE_E current_state; + + /* Statistic info */ + uint64_t icc_msg_in_count; /* ICC message input count */ + uint64_t icc_msg_out_count; /* ICC message Output count */ + uint64_t u_msg_in_count; /* Unknown message Input count */ + uint64_t i_msg_in_count; /* Illegal message Input count */ + + /* Log */ + struct MsgLog msg_log; + + LIST_ENTRY(CSM) next; + LIST_HEAD(csm_if_list, If_info) if_bind_list; +}; +int iccp_csm_send(struct CSM*, char*, int); +int iccp_csm_init_msg(struct Msg**, char*, int); +int iccp_csm_prepare_nak_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_iccp_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_capability_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_rg_connect_msg(struct CSM*, char*, size_t); +int iccp_csm_prepare_rg_disconnect_msg(struct CSM*, char*, size_t); +struct Msg* iccp_csm_dequeue_msg(struct CSM*); +void *iccp_get_csm(); +void iccp_csm_init(struct CSM*); +void iccp_csm_transit(struct CSM*); +void iccp_csm_finalize(struct CSM*); +void iccp_csm_status_reset(struct CSM*, int); +void iccp_csm_stp_role_count(struct CSM *csm); +void iccp_csm_msg_list_finalize(struct CSM*); +void iccp_csm_enqueue_msg(struct CSM*, struct Msg*); +void iccp_csm_fill_icc_rg_id_tlv(struct CSM*, ICCHdr*); +void iccp_csm_correspond_from_msg(struct CSM*, struct Msg*); +void iccp_csm_correspond_from_capability_msg(struct CSM*, struct Msg*); +void iccp_csm_correspond_from_rg_connect_msg(struct CSM*, struct Msg*); +void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM*, struct Msg*); + +int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname); + +#endif /* ICCP_CSM_H_ */ diff --git a/src/iccpd/include/iccp_ifm.h b/src/iccpd/include/iccp_ifm.h new file mode 100644 index 000000000000..ec8e2fe00d5e --- /dev/null +++ b/src/iccpd/include/iccp_ifm.h @@ -0,0 +1,42 @@ +/* +* iccp_ifm.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef ICCP_IFM_H +#define ICCP_IFM_H + +#include + +int iccp_sys_local_if_list_get_init(); + +int iccp_arp_get_init(); + +void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]); + +int do_one_neigh_request (struct nlmsghdr *n); + +void iccp_from_netlink_portchannel_state_handler( char * ifname, int state); + +void iccp_get_if_vlan_info_from_netlink(); + +#endif // LACP_IFM_H + diff --git a/src/iccpd/include/iccp_netlink.h b/src/iccpd/include/iccp_netlink.h new file mode 100644 index 000000000000..6f4a2fce3ad0 --- /dev/null +++ b/src/iccpd/include/iccp_netlink.h @@ -0,0 +1,44 @@ +/* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef ICCP_NETLINK_H +#define ICCP_NETLINK_H +#include +#include +#include +#include +#include +#include + +#include + +#include "../include/system.h" +#include "../include/port.h" + +int iccp_get_port_member_list(struct LocalInterface* lif); +void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg); +void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg); +int iccp_system_init_netlink_socket(); +int iccp_init_netlink_event_fd(struct System *sys); +int iccp_handle_events(struct System * sys); +void iccp_netlink_sync_again(); + +#endif + diff --git a/src/iccpd/include/logger.h b/src/iccpd/include/logger.h new file mode 100644 index 000000000000..6a9b64f05112 --- /dev/null +++ b/src/iccpd/include/logger.h @@ -0,0 +1,67 @@ +/* +* logger.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include +#include + +#include "../include/cmd_option.h" + +typedef enum _iccpd_log_level_t +{ + DEBUG_LOG_LEVEL = 0, + INFO_LOG_LEVEL = 1, + NOTICE_LOG_LEVEL = 2, + WARN_LOG_LEVEL = 3, + ERR_LOG_LEVEL = 4, + CRITICAL_LOG_LEVEL = 5 +} _iccpd_log_level_t; + + +#define LOGBUF_SIZE 1024 +#define ICCPD_UTILS_SYSLOG (syslog) + +#define ICCPD_LOG_CRITICAL(tag, format, args...) write_log(CRITICAL_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_ERR(tag, format, args...) write_log(ERR_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_WARN(tag, format, args...) write_log(WARN_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_NOTICE(tag, format, args...) write_log(NOTICE_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_INFO(tag, format, args...) write_log(INFO_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_DEBUG(tag, format, args...) write_log(DEBUG_LOG_LEVEL, tag, format, ##args) + +struct LoggerConfig { + uint8_t console_log_enabled; + uint8_t log_level; + uint8_t init; +}; + +struct LoggerConfig* logger_get_configuration(); +void log_setup(char* progname, char* path); +void log_finalize(); +void log_init(struct CmdOptionParser* parser); +void write_log(const int level, const char* tag, const char *format, ...); + +#endif /* LOGGER_H_ */ + + diff --git a/src/iccpd/include/mlacp_fsm.h b/src/iccpd/include/mlacp_fsm.h new file mode 100644 index 000000000000..b89d21b780a1 --- /dev/null +++ b/src/iccpd/include/mlacp_fsm.h @@ -0,0 +1,102 @@ +/* +* mlacp_fsm.h +* mLACP finite state machine handler. +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef _MLACP_FSM_H +#define _MLACP_FSM_H + +#include "../include/port.h" + +#define MLCAP_SYNC_PHY_DEV_SEC 1 /*every 1 sec*/ + +#define MLACP(csm_ptr) (csm_ptr->app_csm.mlacp) + +struct CSM; + +enum MLACP_APP_STATE { + MLACP_STATE_INIT, + MLACP_STATE_STAGE1, + MLACP_STATE_STAGE2, + MLACP_STATE_EXCHANGE, + MLACP_STATE_ERROR, +}; + +typedef enum MLACP_APP_STATE MLACP_APP_STATE_E; + +/* for sender only*/ +enum MLACP_SYNC_STATE { + MLACP_SYNC_SYSCONF=0, + MLACP_SYNC_AGGCONF, + MLACP_SYNC_AGGSTATE, + MLACP_SYNC_AGGINFO, + MLACP_SYNC_PEERLINKINFO, + MLACP_SYNC_ARP_INFO, + MLACP_SYNC_DONE, +}; + +typedef enum MLACP_SYNC_STATE MLACP_SYNC_STATE_E; + +struct Remote_System { + uint8_t system_id[ETHER_ADDR_LEN]; + uint16_t system_priority; + uint32_t node_id; +}; + +struct mLACP { + int id; + int sync_req_num; + + MLACP_APP_STATE_E current_state; + MLACP_SYNC_STATE_E sync_state; + + uint8_t wait_for_sync_data; + uint8_t need_to_sync; + uint8_t node_id; + uint8_t system_id[ETHER_ADDR_LEN]; + uint16_t system_priority; + uint8_t system_config_changed; + + struct Remote_System remote_system; + const char* error_msg; + TAILQ_HEAD(mlacp_msg_list, Msg) mlacp_msg_list; + TAILQ_HEAD(arp_msg_list, Msg) arp_msg_list; + TAILQ_HEAD(arp_info_list, Msg) arp_list; + TAILQ_HEAD(mac_msg_list, Msg) mac_msg_list; + TAILQ_HEAD(mac_info_list, Msg) mac_list; + + LIST_HEAD(lif_list, LocalInterface) lif_list; + LIST_HEAD(lif_purge_list, LocalInterface) lif_purge_list; + LIST_HEAD(pif_list, PeerInterface) pif_list; +}; + +void mlacp_init(struct CSM* csm, int all); +void mlacp_finalize(struct CSM* csm); +void mlacp_fsm_transit(struct CSM* csm); +void mlacp_enqueue_msg(struct CSM*, struct Msg*); +struct Msg* mlacp_dequeue_msg(struct CSM*); + +/* from app_csm*/ +extern int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* local_if); +extern int mlacp_unbind_local_if(struct LocalInterface* local_if); + +#endif /* _MLACP_HANDLER_H */ diff --git a/src/iccpd/include/mlacp_link_handler.h b/src/iccpd/include/mlacp_link_handler.h new file mode 100644 index 000000000000..573ba1529720 --- /dev/null +++ b/src/iccpd/include/mlacp_link_handler.h @@ -0,0 +1,51 @@ +/* +* mlacp_link_handler.h +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef __MLACP_LINK_HANDLER__ +#define __MLACP_LINK_HANDLER__ + +#include "../include/iccp_csm.h" + +/***************************************** + * Link Handler + * + * ***************************************/ +void mlacp_portchannel_state_handler(struct CSM* csm, struct LocalInterface* local_if, int po_state); +void mlacp_peerlink_conn_handler(struct CSM* csm); +void mlacp_peerlink_disconn_handler(struct CSM* csm); +void update_stp_peer_link(struct CSM *csm, struct PeerInterface *peer_if, int po_state, int new_create); +void update_peerlink_isolate_from_pif(struct CSM *csm, struct PeerInterface *pif, int po_state, int new_create); +void mlacp_mlag_link_add_handler(struct CSM *csm, struct LocalInterface *lif); +void mlacp_mlag_link_del_handler(struct CSM *csm, struct LocalInterface *lif); +void set_peerlink_mlag_port_learn (struct LocalInterface *lif, int enable); +void peerlink_port_isolate_cleanup(struct CSM* csm); +void update_peerlink_isolate_from_all_csm_lif (struct CSM* csm); + +int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac); +int mlacp_fsm_arp_del(char *ifname, uint32_t ip); + +extern int mclagd_ctl_sock_create(); +extern int mclagd_ctl_sock_accept(int fd); +extern int mclagd_ctl_interactive_process(int client_fd); +int set_nonblocking(int fd); +char *show_ip_str(uint32_t ipv4_addr); +#endif diff --git a/src/iccpd/include/mlacp_sync_prepare.h b/src/iccpd/include/mlacp_sync_prepare.h new file mode 100644 index 000000000000..107d30742d7d --- /dev/null +++ b/src/iccpd/include/mlacp_sync_prepare.h @@ -0,0 +1,54 @@ +/* +* mlacp_sync_prepare.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef __MLACP_SYNC_PREPARE__ +#define __MLACP_SYNC_PREPARE__ + +struct CSM; +/***************************************** + * Tool Function + * + * ***************************************/ + void update_system_id(struct CSM* csm); + +/***************************************** + * LACP Sync + * + * ***************************************/ +int mlacp_sync_with_kernel_callback(); + +/***************************************** + * MLACP Sync + * + * ***************************************/ +int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_buf_size); +int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end); +int mlacp_prepare_for_sys_config(struct CSM* csm,char* buf, size_t max_buf_size); +int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg); +int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg); +int mlacp_prepare_for_heartbeat(struct CSM* csm,char* buf, size_t max_buf_size); +int mlacp_prepare_for_Aggport_state(struct CSM* csm,char* buf, size_t max_buf_size, struct LocalInterface* local_if); +int mlacp_prepare_for_Aggport_config(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* lif, int purge_flag); +int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* port_channel); + +#endif \ No newline at end of file diff --git a/src/iccpd/include/mlacp_sync_update.h b/src/iccpd/include/mlacp_sync_update.h new file mode 100644 index 000000000000..e611a8e2eee2 --- /dev/null +++ b/src/iccpd/include/mlacp_sync_update.h @@ -0,0 +1,45 @@ +/* +* +* mlacp_sync_update.h +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef __MLACP_SYNC_UPDATE__ +#define __MLACP_SYNC_UPDATE__ + +#include "iccp_csm.h" +#include "mlacp_tlv.h" + +/***************************************** + * FSM Sync Update API + * + * ***************************************/ +int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV* tlv); + +int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv); + +int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv); + +int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv); + +void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg); + +int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf); +#endif \ No newline at end of file diff --git a/src/iccpd/include/mlacp_tlv.h b/src/iccpd/include/mlacp_tlv.h new file mode 100644 index 000000000000..ad7640e3a839 --- /dev/null +++ b/src/iccpd/include/mlacp_tlv.h @@ -0,0 +1,413 @@ +/* +* mlacp_tlv.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef MLACP_TLV_H_ +#define MLACP_TLV_H_ + +#include + +#include "../include/msg_format.h" +#include "../include/port.h" + +#define MLACP_SYSCONF_NODEID_MSB_MASK 0x80 +#define MLACP_SYSCONF_NODEID_NODEID_MASK 0x70 +#define MLACP_SYSCONF_NODEID_FREE_MASK 0x0F + +/* +* RFC 7275 +* 7.2.3. mLACP System Config TLV +* [Page 51] +*/ +struct mLACPSysConfigTLV { + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.3.2. */ + uint8_t sys_id[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.3.2. */ + uint16_t sys_priority; + /* + * RFC 7275 + * 7.2.3. mLACP System Config TLV + * [Page 51] + */ + uint8_t node_id; +}__attribute__ ((packed)); + +typedef struct mLACPSysConfigTLV mLACPSysConfigTLV; + +/* +* RFC 7275 +* 7.2.4. mLACP Aggregator Config TLV +* [Page 52] +* NOTE: In this project, Aggregator configuration and state TLV is not support. +*/ +struct mLACPAggConfigTLV { + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ + uint8_t ro_id[8]; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ + uint8_t mac_addr[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ + uint16_t member_ports_priority; + uint8_t flags; + /* + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 54] + */ + uint8_t agg_name_len; + char agg_name[MAX_L_PORT_NAME]; +}__attribute__ ((packed)); + +typedef struct mLACPAggConfigTLV mLACPAggConfigTLV; + +/* +* RFC 7275 +* 7.2.4. mLACP Port Config TLV +* [Page 54] +*/ +struct mLACPPortConfigTLV { + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t port_num; + /* + * RFC 7275 + * 7.2.5. mLACP Port Config TLV + * [Page 55] + */ + uint8_t mac_addr[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t port_priority; + /* IF-MIB [RFC2863] */ + uint32_t port_speed; + /* + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 55] + */ + uint8_t flags; + /* + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 56] + */ + uint8_t port_name_len; + /* IF-MIB [RFC2863] */ + char port_name[MAX_L_PORT_NAME]; + + /* NOS */ + uint8_t orphan; + uint8_t l3_mode; +}__attribute__ ((packed)); + +typedef struct mLACPPortConfigTLV mLACPPortConfigTLV; + +/* +* RFC 7275 +* 7.2.6. mLACP Port Priority TLV +* [Page 56] +*/ +struct mLACPPortPriorityTLV { + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.6. mLACP Port Priority TLV + * [Page 57] + */ + uint16_t op_code; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t port_num; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t last_port_priority; + uint16_t current_port_priority; +}__attribute__ ((packed)); + +typedef struct mLACPPortPriorityTLV mLACPPortPriorityTLV; + +/* +* RFC 7275 +* 7.2.7. mLACP Port State TLV +* [Page 58] +*/ +struct mLACPPortStateTLV { + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.4.2.2, item r. */ + uint8_t partner_sys_id[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.4.2.2, item q. */ + uint16_t partner_sys_priority; + /* [IEEE-802.1AX], Section 5.4.2.2, item u. */ + uint16_t partner_port_num; + /* [IEEE-802.1AX], Section 5.4.2.2, item t. */ + uint16_t partner_port_priority; + /* [IEEE-802.1AX], Section 5.4.2.2, item s. */ + uint16_t partner_key; + /* [IEEE-802.1AX], Section 5.4.2.2, item v. */ + uint8_t partner_state; + /* [IEEE-802.1AX], Section 5.4.2.2, item m. */ + uint8_t actor_state; + /* [IEEE-802.1AX], Section 5.3.4. */ + uint16_t actor_port_num; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* [IEEE-802.1AX], Section 5.4.8 */ + uint8_t selected; + /* + * RFC 7275 + * 7.2.7. mLACP Port State TLV + * [Page 60] + */ + uint8_t port_state; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + + /* NOS */ + uint8_t orphan; + uint16_t port_id; + uint8_t l3_mode; + uint8_t is_peer_link; +}__attribute__ ((packed)); + +typedef struct mLACPPortStateTLV mLACPPortStateTLV; + +/* +* RFC 7275 +* 7.2.8. mLACP Aggregator State TLV +* [Page 60] +* NOTE: In this project, Aggregator configuration and state TLV is not support. +*/ +struct mLACPAggPortStateTLV { + ICCParameter icc_parameter; + /* [IEEE-802.1AX], Section 5.4.2.2, item r. */ + uint8_t partner_sys_id[ETHER_ADDR_LEN]; + /* [IEEE-802.1AX], Section 5.4.2.2, item q. */ + uint16_t partner_sys_priority; + /* [IEEE-802.1AX], Section 5.4.2.2, item s. */ + uint16_t partner_key; + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t agg_id; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; + /* + * RFC 7275 + * 7.2.8. mLACP Aggregator State TLV + * [Page 61] + */ + uint8_t agg_state; +}__attribute__ ((packed)); + +typedef struct mLACPAggPortStateTLV mLACPAggPortStateTLV; + +/* +* RFC 7275 +* 7.2.9. mLACP Synchronization Request TLV +* [Page 61] +*/ +struct mLACPSyncReqTLV { + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 62] + */ + uint16_t req_num; + uint16_t c_bit :1; + /* + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 63] + */ + uint16_t s_bit :1; + uint16_t req_type :14; + /* [IEEE-802.1AX], Section 5.3.4. */ + /* [IEEE-802.1AX], Section 5.4.6. */ + uint16_t port_num_agg_id; + /* [IEEE-802.1AX], Section 5.3.5. */ + uint16_t actor_key; +}__attribute__ ((packed)); + +typedef struct mLACPSyncReqTLV mLACPSyncReqTLV; + +/* +* RFC 7275 +* 7.2.10. mLACP Synchronization Data TLV +* [Page 63] +*/ +struct mLACPSyncDataTLV { + ICCParameter icc_parameter; + /* + * RFC 7275 + * 7.2.10. mLACP Synchronization Data TLV + * [Page 64] + */ + uint16_t req_num; + uint16_t flags; +}__attribute__ ((packed)); + +typedef struct mLACPSyncDataTLV mLACPSyncDataTLV; + +/* VLAN Information TLV*/ +struct mLACPVLANData { + uint16_t vlan_id; +}__attribute__ ((packed)); + +/* +* Port Channel Information TLV +*/ +struct mLACPPortChannelInfoTLV { + ICCParameter icc_parameter; + uint16_t agg_id; + char if_name[MAX_L_PORT_NAME]; + uint8_t if_name_len; + uint8_t l3_mode; + uint32_t ipv4_addr; + uint16_t orphan; + uint16_t po_id; + uint16_t num_of_vlan_id; + struct mLACPVLANData vlanData[0]; +}__attribute__ ((packed)); + +typedef struct mLACPPortChannelInfoTLV mLACPPortChannelInfoTLV; + +/* +* Port PeerLink Information TLV +*/ +struct mLACPPeerLinkInfoTLV { + ICCParameter icc_parameter; + char if_name[MAX_L_PORT_NAME]; + uint8_t port_type; +}__attribute__ ((packed)); + +typedef struct mLACPPeerLinkInfoTLV mLACPPeerLinkInfoTLV; + + +struct mLACPVLANInfoTLV { + ICCParameter icc_parameter; + uint16_t id; /* Local Interface ID, not VLAN ID */ + uint16_t num_of_vlan_id; + struct mLACPVLANData vlanData[0]; +}__attribute__ ((packed)); + +/* +* MAC Information TLV +*/ +struct mLACPMACInfoTLV { + ICCParameter icc_parameter; + uint8_t type;/*add or del*/ + char mac_str[32]; + uint16_t vid; + /*Current if name that set in chip*/ + char ifname[MAX_L_PORT_NAME]; +}__attribute__ ((packed)); + +/* +* ARP Information TLV +*/ +struct mLACPARPInfoTLV { + ICCParameter icc_parameter; + /* Local Interface ID */ + uint8_t type; + char ifname[MAX_L_PORT_NAME]; + uint32_t ipv4_addr; + uint8_t mac_addr[ETHER_ADDR_LEN]; +}__attribute__ ((packed)); + +/* +* NOS: STP Information TLV +*/ +struct stp_msg_s; +struct mLACPSTPInfoTLV { + ICCParameter icc_parameter; + uint8_t stp_msg[0]; +}__attribute__ ((packed)); + +/* +* NOS: Heartbeat +*/ +struct mLACPHeartbeatTLV { + ICCParameter icc_parameter; + uint8_t heartbeat; +}__attribute__ ((packed)); + +enum ARP_OP_TYPE { + ARP_SYNC_LIF, + ARP_SYNC_ADD, + ARP_SYNC_DEL, +}; + +struct ARPMsg { + uint8_t op_type; + char ifname[MAX_L_PORT_NAME]; + uint32_t ipv4_addr; + uint8_t mac_addr[ETHER_ADDR_LEN]; + time_t update_time; +}; + +enum MAC_AGE_TYPE { + MAC_AGE_LOCAL = 1,/*MAC in local switch is ageout*/ + MAC_AGE_PEER = 2, /*MAC in peer switch is ageout*/ +}; + +enum MAC_OP_TYPE { + MAC_SYNC_ADD = 1, + MAC_SYNC_DEL = 2, + MAC_SYNC_ACK = 4, +}; + +enum MAC_TYPE { + MAC_TYPE_STATIC = 1, + MAC_TYPE_DYNAMIC = 2, +}; + +struct MACMsg { + uint8_t op_type;/*add or del*/ + uint8_t fdb_type;/*static or dynamic*/ + char mac_str[32]; + uint16_t vid; + /*Current if name that set in chip*/ + char ifname[MAX_L_PORT_NAME]; + /*if we set the mac to peer-link, origin_ifname store the + original if name that learned from chip*/ + char origin_ifname[MAX_L_PORT_NAME]; + uint8_t age_flag;/*local or peer is age?*/ +}; + +#endif /* MLACP_TLV_H_ */ diff --git a/src/iccpd/include/msg_format.h b/src/iccpd/include/msg_format.h new file mode 100644 index 000000000000..21a338be4d66 --- /dev/null +++ b/src/iccpd/include/msg_format.h @@ -0,0 +1,427 @@ +/* +* msg_format.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef MSG_FORMAT_H_ +#define MSG_FORMAT_H_ +#include +#include + + +#define MAX_MSG_LOG_SIZE 128 + +/* + * RFC 5561 + * 4. Capability Message + * [Page 7] + */ +#define MSG_T_CAPABILITY 0x0202 + +/* + * RFC 7275 + * 6.1.1. ICC Header - Message Length + * [Page 25] + * 2-octet integer specifying the total length of this message in octets, + * excluding the "U-bit", "Message Type", and "Length" fields. + */ +#define MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS 4 + +/* + * RFC 7275 + * 12.1. Message Type Name Space + * [Page 79] + */ +#define MSG_T_RG_CONNECT 0x0700 +#define MSG_T_RG_DISCONNECT 0x0701 +#define MSG_T_NOTIFICATION 0x0702 +#define MSG_T_RG_APP_DATA 0x0703 + +/* + * RFC 7275 + * 12.2. TLV Type Name Space + * [Page 79] + */ +#define TLV_T_ICCP_CAPABILITY 0x0700 +#define TLV_L_ICCP_CAPABILITY 0x4 + +/* + * RFC 7275 + * 12.3. ICC RG Parameter Type Space + * [Page 80] + */ +#define TLV_T_ICC_SENDER_NAME 0x0001 +#define MAX_L_ICC_SENDER_NAME 80 +#define TLV_T_NAK 0x0002 +#define TLV_T_REQUESTED_PROTOCOL_VER 0x0003 +#define TLV_T_DISCONNECT_CODE 0x0004 +#define TLV_L_DISCONNECT_CODE 0x4 +#define TLV_T_ICC_RG_ID 0x0005 +#define TLV_L_ICC_RG_ID 0x4 + +#define TLV_T_MLACP_CONNECT 0x0030 +#define TLV_T_MLACP_DISCONNECT 0x0031 +#define TLV_T_MLACP_SYSTEM_CONFIG 0x0032 +#define TLV_T_MLACP_PORT_CONFIG 0x0033//no support +#define TLV_T_MLACP_PORT_PRIORITY 0x0034//no support +#define TLV_T_MLACP_PORT_STATE 0x0035//no support +#define TLV_T_MLACP_AGGREGATOR_CONFIG 0x0036 +#define TLV_T_MLACP_AGGREGATOR_STATE 0x0037 +#define TLV_T_MLACP_SYNC_REQUEST 0x0038 +#define TLV_T_MLACP_SYNC_DATA 0x0039 +#define TLV_T_MLACP_HEARTBEAT 0x003A +#define TLV_T_MLACP_DISCONNECT_CAUSE 0x003B //not yet + +/* Self define Feature */ +#define TLV_T_MLACP_ORPHAN_PORT 0x1033 //not yet +#define TLV_T_MLACP_PORT_CHANNEL_INFO 0x1034 +#define TLV_T_MLACP_PEERLINK_INFO 0x1035 +#define TLV_T_MLACP_ARP_INFO 0x1036 +#define TLV_T_MLACP_STP_INFO 0x1037//no support +#define TLV_T_MLACP_MAC_INFO 0x1038 + +#define TLV_T_MLACP_LIST_END 0x1039 //list end + +/* Debug */ +static char* get_tlv_type_string(int type) +{ + switch(type) + { + case TLV_T_ICCP_CAPABILITY: + return "TLV_T_ICCP_CAPABILITY"; + case TLV_T_ICC_SENDER_NAME: + return "TLV_T_ICC_SENDER_NAME"; + case TLV_T_NAK: + return "TLV_T_NAK"; + case TLV_T_REQUESTED_PROTOCOL_VER: + return "TLV_T_REQUESTED_PROTOCOL_VER"; + case TLV_T_DISCONNECT_CODE: + return "TLV_T_DISCONNECT_CODE"; + case TLV_T_ICC_RG_ID: + return "TLV_T_ICC_RG_ID"; + case TLV_T_MLACP_CONNECT: + return "TLV_T_MLACP_CONNECT"; + case TLV_T_MLACP_DISCONNECT: + return "TLV_T_MLACP_DISCONNECT"; + case TLV_T_MLACP_SYSTEM_CONFIG: + return "TLV_T_MLACP_SYSTEM_CONFIG"; + case TLV_T_MLACP_PORT_CONFIG: + return "TLV_T_MLACP_PORT_CONFIG"; + case TLV_T_MLACP_PORT_PRIORITY: + return "TLV_T_MLACP_PORT_PRIORITY"; + case TLV_T_MLACP_PORT_STATE: + return "TLV_T_MLACP_PORT_STATE"; + case TLV_T_MLACP_AGGREGATOR_CONFIG: + return "TLV_T_MLACP_AGGREGATOR_CONFIG"; + case TLV_T_MLACP_AGGREGATOR_STATE: + return "TLV_T_MLACP_AGGREGATOR_STATE"; + case TLV_T_MLACP_SYNC_REQUEST: + return "TLV_T_MLACP_SYNC_REQUEST"; + case TLV_T_MLACP_SYNC_DATA: + return "TLV_T_MLACP_SYNC_DATA"; + case TLV_T_MLACP_HEARTBEAT: + return "TLV_T_MLACP_HEARTBEAT"; + case TLV_T_MLACP_DISCONNECT_CAUSE: + return "TLV_T_MLACP_DISCONNECT_CAUSE"; + + /* NOS Feature */ + case TLV_T_MLACP_ORPHAN_PORT: + return "TLV_T_MLACP_ORPHAN_PORT"; + case TLV_T_MLACP_PORT_CHANNEL_INFO: + return "TLV_T_MLACP_PORT_CHANNEL_INFO"; + case TLV_T_MLACP_PEERLINK_INFO: + return "TLV_T_MLACP_PEERLINK_INFO"; + case TLV_T_MLACP_ARP_INFO: + return "TLV_T_MLACP_ARP_INFO"; + case TLV_T_MLACP_MAC_INFO: + return "TLV_T_MLACP_MAC_INFO"; + case TLV_T_MLACP_STP_INFO: + return "TLV_T_MLACP_STP_INFO"; + } + return "UNKNOWN"; +} + +/* + * RFC 7275 + * 12.4. Status Code Name Space + * [Page 81] + */ +#define STATUS_CODE_U_ICCP_RG 0x00010001 +#define STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED 0x00010002 +#define STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED 0x00010003 +#define STATUS_CODE_ICCP_APP_NOT_IN_RG 0x00010004 +#define STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER 0x00010005 +#define STATUS_CODE_ICCP_REJECTED_MSG 0x00010006 +#define STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED 0x00010007 +#define STATUS_CODE_ICCP_RG_REMOVED 0x00010010 +#define STATUS_CODE_ICCP_APP_REMOVED_FROM_RG 0x00010011 + + +/* Debug */ +static char* get_status_string(int status) +{ + switch(status) + { + case STATUS_CODE_U_ICCP_RG: + return "Unknown ICCP RG"; + case STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED: + return "ICCP Connection Count Exceeded"; + case STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED: + return "ICCP Application Connection Count Exceede"; + case STATUS_CODE_ICCP_APP_NOT_IN_RG: + return "ICCP Application not in RG"; + case STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER: + return "Incompatible ICCP Protocol Version"; + case STATUS_CODE_ICCP_REJECTED_MSG: + return "ICCP Rejected Message"; + case STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED: + return "ICCP Administratively Disabled"; + case STATUS_CODE_ICCP_RG_REMOVED: + return "ICCP RG Removed"; + case STATUS_CODE_ICCP_APP_REMOVED_FROM_RG: + return "ICCP Application Removed from RG"; + } + return "UNKNOWN"; +} +/* + * RFC 5036 + * 3.5. LDP Messages + * [Page 44] + */ +struct LDPHdr { + uint16_t u_bit :1; + uint16_t msg_type :15; + uint16_t msg_len; + uint32_t msg_id; +}__attribute__ ((packed)); + +typedef struct LDPHdr LDPHdr; + +/* + * RFC 7275 + * 6.1.1. ICC Header + * [Page 24] + */ +struct ICCRGIDTLV { + uint16_t type; + uint16_t len; + uint32_t icc_rg_id; +}__attribute__ ((packed)); + +typedef struct ICCRGIDTLV ICCRGIDTLV; + +struct ICCHdr { + LDPHdr ldp_hdr; + ICCRGIDTLV icc_rg_id_tlv; +}__attribute__ ((packed)); + +typedef struct ICCHdr ICCHdr; + +/* + * RFC 7275 + * 6.1.2. ICC Parameter Encoding + * [Page 26] + */ +struct ICCParameter { + uint16_t u_bit :1; + uint16_t f_bit :1; + uint16_t type :14; + uint16_t len; +}__attribute__ ((packed)); + +typedef struct ICCParameter ICCParameter; + +/* + * RFC 7275 + * 6.2.1. ICC Sender Name TLV + * [Page 28] + */ +struct ICCSenderNameTLV { + ICCParameter icc_parameter; + char sender_name[MAX_L_ICC_SENDER_NAME]; +}__attribute__ ((packed)); + +typedef struct ICCSenderNameTLV ICCSenderNameTLV; + +/* + * RFC 7275 + * 6.3. RG Disconnect Message + * [Page 29] + */ +struct DisconnectCodeTLV { + ICCParameter icc_parameter; + uint32_t iccp_status_code; +}__attribute__ ((packed)); + +typedef struct DisconnectCodeTLV DisconnectCodeTLV; + +/* + * RFC 7275 + * 6.4.1. Notification Message TLVs + * [Page 32] + */ +struct NAKTLV { + ICCParameter icc_parameter; + uint32_t iccp_status_code; + uint32_t rejected_msg_id; +}__attribute__ ((packed)); + +typedef struct NAKTLV NAKTLV; + +/* + * RFC 7275 + * 6.4.1. Notification Message TLVs + * [Page 34] + */ +struct RequestedProtocolVerTLV { + ICCParameter icc_parameter; + uint16_t connection_ref; + uint16_t requested_ver; +}__attribute__ ((packed)); + +typedef struct RequestedProtocolVerTLV RequestedProtocolVerTLV; + +/* + * RFC 7275 + * 8. LDP Capability Negotiation + * [Page 65] + */ +struct LDPICCPCapabilityTLV { + ICCParameter icc_parameter; + uint16_t s_bit :1; + uint16_t reserved :15; + uint8_t major_ver; + uint8_t minior_ver; +}__attribute__ ((packed)); + +typedef struct LDPICCPCapabilityTLV LDPICCPCapabilityTLV; + +/* + * RFC 7275 + * 7.2.1. mLACP Connect TLV + * [Page 47] + */ +struct AppConnectTLV { + ICCParameter icc_parameter; + uint16_t protocol_version; + uint16_t a_bit :1; + uint16_t reserved :15; + + /* Optional Sub-TLVs */ + /* No optional sub-TLVs in this version */ +}__attribute__ ((packed)); + +typedef struct AppConnectTLV AppConnectTLV; + +/* + * RFC 7275 + * 7.2.2. mLACP Disconnect TLV + * [Page 48] + */ +struct AppDisconnectTLV { + ICCParameter icc_parameter; + + /* Optional Sub-TLVs */ + /* mLACP Disconnect Cause TLV */ +}__attribute__ ((packed)); + +typedef struct AppDisconnectTLV AppDisconnectTLV; + +/* + * RFC 7275 + * 7.2.2.1. mLACP Disconnect Cause TLV + * [Page 49] + */ +struct AppDisconnectCauseTLV { + ICCParameter iccp_parameter; + + /* Disconnect Cause String */ + char cause_string[0]; /* Trick */ +}__attribute__ ((packed)); + +/*syncd send msg type to iccpd*/ +typedef enum mclag_syncd_msg_type_e_ { + MCLAG_SYNCD_MSG_TYPE_NONE = 0, + MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1 +}mclag_syncd_msg_type_e; + +typedef enum mclag_msg_type_e_ { + MCLAG_MSG_TYPE_NONE = 0, + MCLAG_MSG_TYPE_PORT_ISOLATE = 1, + MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE = 2, + MCLAG_MSG_TYPE_FLUSH_FDB = 3, + MCLAG_MSG_TYPE_SET_MAC = 4, + MCLAG_MSG_TYPE_SET_FDB = 5, + MCLAG_MSG_TYPE_GET_FDB_CHANGES = 20 +}mclag_msg_type_e; + + +typedef enum mclag_sub_option_type_e_ { + MCLAG_SUB_OPTION_TYPE_NONE = 0, + MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC = 1, + MCLAG_SUB_OPTION_TYPE_ISOLATE_DST = 2, + MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE = 3, + MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4, + MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC = 5, + MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6 +} mclag_sub_option_type_e; + + +struct IccpSyncdHDr { + uint8_t ver; + uint8_t type; + uint16_t len; +}; + +typedef struct mclag_sub_option_hdr_t_ { + + uint8_t op_type; + + /* + * Length of option value, not including the header. + */ + uint16_t op_len; + uint8_t data[]; +}mclag_sub_option_hdr_t; + +struct mclag_fdb_info +{ + unsigned char mac[32]; + unsigned int vid; + unsigned char port_name[32]; + short type;/*dynamic or static*/ + short op_type;/*add or del*/ +}; + +/* For storing message log: For Notification TLV */ +struct MsgTypeSet { + uint32_t msg_id; + uint16_t type; + uint16_t tlv; + +}; + +struct MsgLog { + struct MsgTypeSet msg[MAX_MSG_LOG_SIZE]; + uint32_t end_index; +}; + +#endif /* MSG_FORMAT_H_ */ diff --git a/src/iccpd/include/port.h b/src/iccpd/include/port.h new file mode 100644 index 000000000000..78743d0a4e48 --- /dev/null +++ b/src/iccpd/include/port.h @@ -0,0 +1,149 @@ +/* +* port.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef PORT_H_ +#define PORT_H_ + +#include +#include +#include + +#define ETHER_ADDR_LEN 6 +/* +* RFC 7275 +* 7.2.4. mLACP Port Config TLV +* [Page 56] +*/ +#define MAX_L_PORT_NAME 20 + +/* defined in RFC 7275 - 7.2.7 (p.59) */ +#define PORT_STATE_UP 0x00 +#define PORT_STATE_DOWN 0x01 +#define PORT_STATE_ADMIN_DOWN 0x02 +#define PORT_STATE_TEST 0x03 + +/* Interface Type */ +#define IF_T_UNKNOW -1 +#define IF_T_PORT 0 +#define IF_T_PORT_CHANNEL 1 +#define IF_T_VLAN 2 + +typedef struct { + char *ifname; + int type; +} itf_type_t; + +struct If_info{ + char name[MAX_L_PORT_NAME]; + LIST_ENTRY(If_info) csm_next; +}; + +struct VLAN_ID { + uint16_t vid; + uint16_t vlan_removed; + struct LocalInterface* vlan_itf; /* loacl vlan interface */ + LIST_ENTRY(VLAN_ID) port_next; +}; + +struct PeerInterface { + int ifindex; + int type; + char name[MAX_L_PORT_NAME]; + + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint8_t state; + uint32_t ipv4_addr; + + uint8_t l3_mode; + uint8_t is_peer_link; + int po_id; + uint8_t po_active; + + struct CSM* csm; + + LIST_ENTRY(PeerInterface) mlacp_next; + LIST_HEAD(peer_vlan_list, VLAN_ID) vlan_list; +}; + +struct LocalInterface { + int ifindex; + int type; + char name[MAX_L_PORT_NAME]; + + uint8_t mac_addr[ETHER_ADDR_LEN]; + uint8_t mac_addr_ori[ETHER_ADDR_LEN]; + uint8_t state; + uint32_t ipv4_addr; + uint8_t prefixlen; + + uint8_t l3_mode; + uint8_t is_peer_link; + char portchannel_member_buf[512]; + uint8_t is_arp_accept; + int po_id; /* Port Channel ID */ + uint8_t po_active; /* Port Channel is in active status? */ + int mlacp_state; /* Record mlacp state */ + uint8_t isolate_to_peer_link; + + struct CSM* csm; + + uint8_t changed; + uint8_t port_config_sync; + + LIST_HEAD(local_vlan_list, VLAN_ID) vlan_list; + + LIST_ENTRY(LocalInterface) system_next; + LIST_ENTRY(LocalInterface) system_purge_next; + LIST_ENTRY(LocalInterface) mlacp_next; + LIST_ENTRY(LocalInterface) mlacp_purge_next; +}; + +struct LocalInterface* local_if_create(int ifindex, char* ifname, int type); +struct LocalInterface* local_if_find_by_name(const char* ifname); +struct LocalInterface* local_if_find_by_ifindex(int ifindex); +struct LocalInterface* local_if_find_by_po_id(int po_id); + +void local_if_destroy(char *ifname); +void local_if_change_flag_clear(void); +void local_if_purge_clear(void); +int local_if_is_l3_mode(struct LocalInterface* local_if); + +void local_if_init(struct LocalInterface*); +void local_if_finalize(struct LocalInterface*); + +void ether_mac_set_addr_with_if_name(char* name, uint8_t* mac); + +struct PeerInterface* peer_if_create(struct CSM* csm, int peer_if_number, int type); +struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name); + +void peer_if_destroy(struct PeerInterface* pif); + +/* VLAN manipulation */ +int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid); +void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid); +void local_if_del_all_vlan(struct LocalInterface* lif); + +/* ARP manipulation */ +int set_sys_arp_accept_flag(char* ifname, int flag); + +#endif /* PORT_H_ */ diff --git a/src/iccpd/include/scheduler.h b/src/iccpd/include/scheduler.h new file mode 100644 index 000000000000..156b82247242 --- /dev/null +++ b/src/iccpd/include/scheduler.h @@ -0,0 +1,58 @@ +/* +* scheduler.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef SCHEDULER_H_ +#define SCHEDULER_H_ + +#include + +#include +#include +#include + +#include +#include +#include + +struct CSM; + +#define CONNECT_INTERVAL_SEC 1 +#define CONNECT_TIMEOUT_MSEC 100 +#define HEARTBEAT_TIMEOUT_SEC 15 +#define TRANSIT_INTERVAL_SEC 1 +#define EPOLL_TIMEOUT_MSEC 100 + +int scheduler_prepare_session(struct CSM*); +int scheduler_check_csm_config(struct CSM*); +int scheduler_unregister_sock_read_event_callback(struct CSM*); +void scheduler_session_disconnect_handler(struct CSM*); +void scheduler_init(); +void scheduler_finalize(); +void scheduler_loop(); +void scheduler_start(); +void scheduler_server_sock_init(); +int scheduler_csm_read_callback(struct CSM* csm) ; +int iccp_get_server_sock_fd(); +int scheduler_server_accept(); + +#endif /* SCHEDULER_H_ */ diff --git a/src/iccpd/include/system.h b/src/iccpd/include/system.h new file mode 100644 index 000000000000..f28236e1c238 --- /dev/null +++ b/src/iccpd/include/system.h @@ -0,0 +1,83 @@ +/* +* system.h +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#ifndef SYSTEM_H_ +#define SYSTEM_H_ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "../include/port.h" + +struct CSM; + +struct System { + int server_fd;/* Peer-Link Socket*/ + int sync_fd; + int sync_ctrl_fd; + int arp_receive_fd; + int epoll_fd; + + struct nl_sock * genric_sock; + int genric_sock_seq; + int family; + struct nl_sock * route_sock; + int route_sock_seq; + struct nl_sock * genric_event_sock; + struct nl_sock * route_event_sock; + + /* Info List*/ + LIST_HEAD(csm_list, CSM) csm_list; + LIST_HEAD(lif_all_list, LocalInterface) lif_list; + LIST_HEAD(lif_purge_all_list, LocalInterface) lif_purge_list; + + /* Settings */ + char* log_file_path; + char* cmd_file_path; + char* config_file_path; + char* mclagdctl_file_path; + int pid_file_fd; + int telnet_port; + fd_set readfd; /*record socket need to listen*/ + int readfd_count; + time_t csm_trans_time; + int need_sync_team_again; + int need_sync_netlink_again; +}; + +struct CSM* system_create_csm(); +struct CSM* system_get_csm_by_peer_ip(const char*); +struct CSM* system_get_csm_by_mlacp_id(int id); +struct System* system_get_instance(); +void system_finalize(); +void system_init(struct System*); + +#endif /* SYSTEM_H_ */ diff --git a/src/iccpd/src/Makefile b/src/iccpd/src/Makefile new file mode 100644 index 000000000000..5e8cebc703c0 --- /dev/null +++ b/src/iccpd/src/Makefile @@ -0,0 +1,55 @@ +LIBNL_CFLAGS = -I/usr/include/libnl3 +LIBNL_LIBS = -lnl-cli-3 -lnl-genl-3 -lnl-nf-3 -lnl-route-3 -lnl-3 + +CC = gcc +SOURCES = app_csm.c cmd_option.c iccp_cli.c iccp_cmd_show.c iccp_cmd.c \ +iccp_csm.c iccp_ifm.c iccp_main.c logger.c \ +port.c scheduler.c system.c iccp_consistency_check.c \ +mlacp_link_handler.c \ +mlacp_sync_prepare.c mlacp_sync_update.c\ +mlacp_fsm.c \ +iccp_netlink.c + +OBJECTS = app_csm.o cmd_option.o iccp_cli.o iccp_cmd_show.o iccp_cmd.o \ +iccp_csm.o iccp_ifm.o iccp_main.o logger.o \ +port.o scheduler.o system.o iccp_consistency_check.o\ +mlacp_link_handler.o \ +mlacp_sync_prepare.o mlacp_sync_update.o \ +mlacp_fsm.o \ +iccp_netlink.o + +HEADERS = ../include/app_csm.h ../include/cmd_option.h ../include/iccp_cli.h \ +../include/iccp_cmd_show.h \ +../include/iccp_csm.h ../include/iccp_ifm.h \ +../include/logger.h ../include/mlacp_fsm.h \ +../include/mlacp_tlv.h ../include/msg_format.h ../include/port.h \ +../include/scheduler.h ../include/system.h \ +../include/iccp_consistency_check.h ../include/route_info.h \ +../include/iccp_netlink.h + +//CFLAGS = -g -O2 -fstack-protector-strong -Wformat -Werror=format-security $(LIBNL_CFLAGS) -I../include/ +CFLAGS = -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -I../include/ $(LIBNL_CFLAGS) +LDFLAGS = $(LIBNL_LIBS) -lpthread +LDADD = $(LIBZEBRA_BIN) + +all: iccpd + +%.o: %.c $(HEADERS) + +iccpd: $(OBJECTS) + $(CC) -o ../iccpd $(OBJECTS) $(LDFLAGS) + +DEPS = $(patsubst %.o, %.d, $(OBJECTS)) + +-include $(DEPS) +%.d:%.c + @set -e; rm -f $@; \ + gcc -MM $(CPPFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + + + +.PHONY: clean +clean: + -rm -f $(OBJECTS) $(DEPS) ../iccpd diff --git a/src/iccpd/src/app_csm.c b/src/iccpd/src/app_csm.c new file mode 100644 index 000000000000..5e4ccf42c45e --- /dev/null +++ b/src/iccpd/src/app_csm.c @@ -0,0 +1,312 @@ +/* +* app_csm.c +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include + +#include "../include/iccp_csm.h" +#include "../include/logger.h" +#include "../include/scheduler.h" +#include "../include/system.h" + +/***************************************** +* Define +* +* ***************************************/ +#define APP_CSM_QUEUE_REINIT(list) \ + {\ + struct Msg* msg = NULL;\ + while (!TAILQ_EMPTY(&(list))) {\ + msg = TAILQ_FIRST(&(list));\ + TAILQ_REMOVE(&(list), msg, tail);\ + free(msg->buf);\ + free(msg);\ + }\ + TAILQ_INIT(&(list));\ + } + +/* Application State Machine instance initialization */ +void app_csm_init(struct CSM* csm, int all) +{ + if (csm == NULL ) + return; + + APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); + + if(all) + { + bzero(&(csm->app_csm), sizeof(struct AppCSM)); + APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); + } + + csm->app_csm.current_state = APP_NONEXISTENT; + csm->app_csm.rx_connect_msg_id = 0; + csm->app_csm.tx_connect_msg_id = 0; + csm->app_csm.invalid_msg_id = 0; + csm->app_csm.invalid_msg = 0; + csm->app_csm.nak_msg = 0; + + mlacp_init(csm, all); +} + +/* Application State Machine instance tear down */ +void app_csm_finalize(struct CSM* csm) +{ + mlacp_finalize(csm); +} + +/* Application State Machine Transition */ +void app_csm_transit(struct CSM* csm) +{ + if (csm == NULL ) + return; + + /* torn down event */ + if (csm->app_csm.current_state != APP_NONEXISTENT && csm->sock_fd <= 0) + { + csm->app_csm.current_state = APP_NONEXISTENT; + return; + } + + if(csm->app_csm.current_state != APP_OPERATIONAL && csm->current_state == ICCP_OPERATIONAL) + { + csm->app_csm.current_state = APP_OPERATIONAL; + } + + return; +} + +/* Add received message into application message list */ +void app_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + ICCParameter* param = NULL; + NAKTLV* naktlv = NULL; + int tlv = -1; + int i = 0; + + if (csm == NULL ) + { + if (msg != NULL ) + free(msg); + return; + } + if (msg == NULL ) + return; + + icc_hdr = (ICCHdr*) msg->buf; + param = (ICCParameter*) &msg->buf[sizeof(struct ICCHdr)]; + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + if(param->type > TLV_T_MLACP_CONNECT && param->type < TLV_T_MLACP_LIST_END) + mlacp_enqueue_msg(csm, msg); + else + TAILQ_INSERT_TAIL(&(csm->app_csm.app_msg_list), msg, tail); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + { + naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; + for(i=0; irejected_msg_id == csm->msg_log.msg[i].msg_id) + { + tlv = csm->msg_log.msg[i].tlv; + break; + } + } + + if(tlv > TLV_T_MLACP_CONNECT && tlv <= TLV_T_MLACP_MAC_INFO) + mlacp_enqueue_msg(csm, msg); + else + TAILQ_INSERT_TAIL(&(csm->app_csm.app_msg_list), msg, tail); + } + else + { + /* This packet is not for me, ignore it. */ + ICCPD_LOG_DEBUG(__FUNCTION__, "Ignore the packet with msg_type = %d", icc_hdr->ldp_hdr.msg_type); + } +} + +/* Get received message from message list */ +struct Msg* app_csm_dequeue_msg(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (!TAILQ_EMPTY(&(csm->app_csm.app_msg_list))) + { + msg = TAILQ_FIRST(&(csm->app_csm.app_msg_list)); + TAILQ_REMOVE(&(csm->app_csm.app_msg_list), msg, tail); + } + + return msg; +} + +/* APP NAK message handle function */ +int app_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + NAKTLV* naktlv = (NAKTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); + + ICCPD_LOG_DEBUG(__FUNCTION__, " Response NAK"); + memset(buf, 0, max_buf_size); + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_NOTIFICATION; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + naktlv->icc_parameter.u_bit = 0; + naktlv->icc_parameter.f_bit = 0; + naktlv->icc_parameter.type = TLV_T_NAK; + naktlv->icc_parameter.len = sizeof(NAKTLV) - 4; + + naktlv->iccp_status_code = STATUS_CODE_ICCP_REJECTED_MSG; + naktlv->rejected_msg_id = csm->app_csm.invalid_msg_id; + + return msg_len; +} + +int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) +{ + struct LocalInterface* lifp = NULL; + struct LocalInterface* lif_po = NULL; + + if (csm == NULL || lif == NULL) + return -1; + + if (lif->csm == csm) + return 0; + + /* remove purge from the csm*/ + do + { + LIST_FOREACH(lifp, &(MLACP(csm).lif_purge_list), mlacp_purge_next) + { + if (lifp == lif) + break; + } + if (lifp) + LIST_REMOVE(lifp, mlacp_purge_next); + } while (lifp); + + /* already join csm?*/ + LIST_FOREACH(lifp, &(MLACP(csm).lif_list), mlacp_next) + { + if (lifp == lif) + return 0; + } + + /* join another csm beofre? remove from csm*/ + if (lif->csm != NULL) + mlacp_unbind_local_if(lif); + + /* join new csm*/ + LIST_INSERT_HEAD(&(MLACP(csm).lif_list), lif, mlacp_next); + lif->csm = csm; + if (lif->type == IF_T_PORT_CHANNEL) lif->port_config_sync = 1; + + ICCPD_LOG_INFO(__FUNCTION__, "%s: MLACP bind on csm %p", lif->name, csm); + if (lif->type == IF_T_PORT_CHANNEL) + return 0; + + /* if join a po member, needs to check po joined also*/ + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type == IF_T_PORT_CHANNEL && lif_po->po_id == lif->po_id) + return 0; + } + + if (lif_po == NULL) + { + lif_po = local_if_find_by_po_id(lif->po_id); + if (lif_po == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, + "Failed to find port_channel instance for %d.", + lif->po_id); + return -1; + } + + lif_po->csm = csm; + LIST_INSERT_HEAD(&(MLACP(csm).lif_list), lif_po, mlacp_next); + lif_po->port_config_sync = 1; + ICCPD_LOG_INFO(__FUNCTION__, "Add port_channel %d into local_if_list in CSM %p.", lif->po_id, csm); + } + + return 0; +} + +int mlacp_unbind_local_if(struct LocalInterface* lif) +{ + if (lif == NULL ) + return -1; + + if (lif->csm == NULL ) + return 0; + + ICCPD_LOG_INFO(__FUNCTION__, "%s: MLACP un-bind from csm %p", lif->name, lif->csm); + LIST_REMOVE(lif, mlacp_next); + + if (MLACP(lif->csm).current_state == MLACP_STATE_EXCHANGE && lif->type == IF_T_PORT_CHANNEL) + LIST_INSERT_HEAD(&(MLACP(lif->csm).lif_purge_list), lif, mlacp_purge_next); + if (lif->type == IF_T_PORT) + lif->po_id = -1; + lif->csm = NULL; + + return 0; +} + +int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname) +{ + struct System* sys = NULL; + struct LocalInterface *lif_po = NULL; + + sys = system_get_instance(); + if(sys == NULL) + return 0; + + if (csm == NULL) + return 0; + + /* bind po first*/ + lif_po = local_if_find_by_name(ifname); + if (lif_po) + { + mlacp_bind_local_if(csm, lif_po); + iccp_get_port_member_list(lif_po); + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, + "%s: Failed to find a port instance .", + ifname); + return 0; + } + /* process link state handler after attaching it.*/ + + mlacp_mlag_link_add_handler(csm, lif_po); + + /*ICCPD_LOG_WARN(tag, "po%d active = %d\n", po_id, po_is_active);*/ + return 0; +} + diff --git a/src/iccpd/src/cmd_option.c b/src/iccpd/src/cmd_option.c new file mode 100644 index 000000000000..21be3ceebd59 --- /dev/null +++ b/src/iccpd/src/cmd_option.c @@ -0,0 +1,262 @@ +/* +* cmd_option.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include "../include/cmd_option.h" + +struct CmdOption* cmd_option_find(struct CmdOptionParser* parser, char* opt_name) +{ + struct CmdOption* opt = NULL; + + if (opt_name == NULL) + return NULL; + + LIST_FOREACH(opt, &(parser->option_list), next) + { + if (strcmp(opt->option, opt_name) == 0) + return opt; + } + + return NULL; +} + +void cmd_option_delete(struct CmdOption* opt) +{ + if (opt == NULL) + return; + + LIST_REMOVE(opt, next); + if (opt->option != NULL) + free(opt->option); + if (opt->parameter != NULL) + free(opt->parameter); + if (opt->desc != NULL) + free(opt->desc); + free(opt); +} + +struct CmdOption* cmd_option_add(struct CmdOptionParser* parser, char* opt_name) +{ + struct CmdOption* opt = NULL; + + if (opt_name == NULL) + return NULL; + if ((opt = cmd_option_find(parser, opt_name)) != NULL) + return opt; + + if ((opt = (struct CmdOption*) malloc(sizeof(struct CmdOption))) == NULL) + { + strerror(errno); + } + else + { + opt->option = opt_name; + opt->parameter = NULL; + opt->desc = NULL; + LIST_INSERT_HEAD(&(parser->option_list), opt, next); + } + + return opt; +} + +static void cmd_option_register(struct CmdOptionParser* parser, char* syntax, char* desc) +{ + char buf[OPTION_MAX_LEN]; + struct CmdOption* opt = NULL; + char* opt_name = NULL; + char* param = NULL; + char* desc_copy = NULL; + char* token = NULL; + + if (parser == NULL) + return; + if (syntax == NULL) + return; + + memset(buf, 0, OPTION_MAX_LEN); + snprintf(buf, OPTION_MAX_LEN - 1, "%s", syntax); + + if ((token = strtok(buf, " ")) == NULL) + return; + + opt_name = strdup(token); + if ((token = strtok(NULL, " ")) != NULL) + param = strdup(token); + desc_copy = strdup(desc); + if ((opt = cmd_option_find(parser, opt_name)) != NULL) + goto failed; + if ((opt = cmd_option_add(parser, opt_name)) == NULL) + { + goto failed; + } + opt->parameter = param; + opt->desc = desc_copy; + + return; + +failed: + if(opt_name) + free(opt_name); + if (desc_copy != NULL) + free(desc_copy); + if (param != NULL) + free(param); + if (opt != NULL) + free(opt); +} + +void cmd_option_parser_init(struct CmdOptionParser* parser) +{ + if (parser == NULL) + return; + + LIST_INIT(&parser->option_list); + cmd_option_register(parser, "-l ", "Set log file path.\n(Default: /var/log/iccpd.log)"); + cmd_option_register(parser, "-p ", "Set the port used for telnet listening port.\n(Default: 2015)"); + cmd_option_register(parser, "-c", "Dump log message to console. (Default: No)"); + cmd_option_register(parser, "-h", "Show the usage."); +} + +void cmd_option_parser_finalize(struct CmdOptionParser* parser) +{ + while (!LIST_EMPTY(&(parser->option_list))) + { + struct CmdOption* opt = NULL; + opt = LIST_FIRST(&(parser->option_list)); + cmd_option_delete(opt); + } +} + +void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_name) +{ + char buf[MSG_LEN]; + struct CmdOption* opt = NULL; + int index, begin, length; + char first_line = 0; + + fprintf(stdout, "Usage: %s [Options]\n", prog_name); + fprintf(stdout, "\n"); + fprintf(stdout, "Options:\n"); + LIST_FOREACH(opt, &(parser->option_list), next) + { + index = 0; + begin = 0; + length = 0; + first_line = 1; + memset(buf, 0, MSG_LEN); + if (opt->parameter != NULL) + snprintf(buf, MSG_LEN - 1, "%s %s", opt->option, opt->parameter); + else + snprintf(buf, MSG_LEN - 1, "%s", opt->option); + fprintf(stdout, "%24s ", buf); + while (index < strlen(opt->desc)) + { + while (index < strlen(opt->desc) + && opt->desc[index] != '\n' && length < 49) + { + ++index; + ++length; + } + memset(buf, 0, MSG_LEN); + strncpy(buf, &(opt->desc[begin]), length); + if (length == 49 && index < strlen(opt->desc) + && opt->desc[index] != '\n' + && opt->desc[index - 1] != ' ' + && opt->desc[index] != ' ') + { + buf[length] = '-'; + buf[length + 1] = '\0'; + } + if (length < 49) ++index; + begin = index; + length = 0; + if (first_line != 0) + { + fprintf(stdout, "%-52s\n", buf); + first_line = 0; + } + else + fprintf(stdout, "%28c%-52s\n", ' ', buf); + } + fflush(stdout); + } +} + +int cmd_option_parser_parse(struct CmdOptionParser* parser, int argc, char* argv[]) +{ + int index = 1; + struct CmdOption* opt = NULL; + char* opt_name = NULL; + char* val = NULL; + int num = 0; + + if (parser == NULL) + return -255; + + while (index < argc) + { + opt_name = argv[index]; + opt = cmd_option_find(parser, opt_name); + if (opt == NULL) + { + fprintf(stderr, "Unknown option %s, skip it.\n", opt_name); + ++index; + continue; + } + + if (opt->parameter != NULL) + { + ++index; + if (index >= argc) + { + fprintf(stderr, "Error: Insufficient parameter for option %s\n", opt_name); + cmd_option_parser_dump_usage(parser, argv[0]); + return -1; + } + val = argv[index]; + } + + if (strncmp(opt_name, "-h", 2) == 0) + { + cmd_option_parser_dump_usage(parser, argv[0]); + return -1; + } + + if (strncmp(opt_name, "-l", 2) == 0) + parser->log_file_path = val; + + if (strncmp(opt_name, "-p", 2) == 0) + { + num = atoi(val); + if (num > 0 && num < 65535) + parser->telnet_port = num; + } + else if (strncmp(opt_name, "-c", 2) == 0) + parser->console_log = 1; + else + fprintf(stderr, "Unknown option name %s, skip it.\n", opt_name); + + ++index; + } + + return 0; +} diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c new file mode 100644 index 000000000000..73eb16ddacd6 --- /dev/null +++ b/src/iccpd/src/iccp_cli.c @@ -0,0 +1,363 @@ +/* +* iccp_cli.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_link_handler.h" + +/* +* 'id <1-65535>' command +*/ +int set_mc_lag_id( struct CSM *csm, uint16_t id) +{ + if (!csm) return -1; + + ICCPD_LOG_INFO(__FUNCTION__, "Set mlag-id : %d", id); + + /* Mlag-ID, RG-ID, MLACP-ID + Temporary let the three id be the same*/ + csm->mlag_id = id; + csm->iccp_info.icc_rg_id = id; + csm->app_csm.mlacp.id = id; + return 0; +} + +int unset_mc_lag_id( struct CSM *csm, uint16_t id) +{ + if (!csm) return -1; + + /* Mlag-ID, RG-ID, MLACP-ID*/ + csm->mlag_id = 0; + csm->iccp_info.icc_rg_id = 0; + csm->app_csm.mlacp.id = 0; + + iccp_csm_finalize(csm); + + return 0; +} + +/* +* 'peer-link WORD' command +*/ +int set_peer_link(int mid, const char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface *lif = NULL; + size_t len = 0; + + len = strlen(ifname); + + if (strncmp(ifname, "Eth", 3) != 0 && strncmp(ifname, "Por", 3) != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Peer-link is %s, must be Ethernet or PortChannel", ifname); + return -1; + } + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + + if (len > IFNAMSIZ) return -1; + + if (strlen(csm->peer_itf_name) > 0) + { + if(strcmp(csm->peer_itf_name, ifname) == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer-link not be changed"); + return 0; + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Change peer-link : %s -> %s", + csm->peer_itf_name, ifname); + + scheduler_session_disconnect_handler(csm); + + if(csm->peer_link_if) + { + csm->peer_link_if->is_peer_link = 0; + csm->peer_link_if = NULL; + } + } + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Set mlag %d peer-link : %s", + csm->mlag_id,ifname); + } + + memset(csm->peer_itf_name, 0, IFNAMSIZ); + memcpy(csm->peer_itf_name, ifname, len); + + /* update peer-link link handler*/ + lif = local_if_find_by_name(csm->peer_itf_name); + if (lif) + { + csm->peer_link_if = lif; + lif->is_peer_link = 1; + MLACP(csm).system_config_changed = 1; + + if(lif->type == IF_T_PORT_CHANNEL) + iccp_get_port_member_list(lif); + } + + return 0; +} + +int unset_peer_link(int mid) +{ + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*must be enabled mac learn*/ + set_peerlink_mlag_port_learn(csm->peer_link_if, 1); + } + + /* Clean all port block*/ + peerlink_port_isolate_cleanup(csm); + + /* update peer-link link handler*/ + scheduler_session_disconnect_handler(csm); + + /* clean peer-link*/ + memset(csm->peer_itf_name, 0, IFNAMSIZ); + if(csm->peer_link_if) + { + csm->peer_link_if->is_peer_link = 0; + csm->peer_link_if = NULL; + MLACP(csm).system_config_changed = 1; + } + + return 0; +} + +/* +* 'local ip address A.B.C.D' command +*/ +int set_local_address(int mid, const char* addr) +{ + struct CSM* csm = NULL; + size_t len = 0; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + if (addr == NULL) return -1; + + if (strlen(csm->sender_ip) > 0) { + if (strcmp(csm->sender_ip, addr) == 0) { + ICCPD_LOG_INFO(__FUNCTION__, "Local-address not be changed"); + return 0; + } + else { + ICCPD_LOG_INFO(__FUNCTION__, "Change local-address : %s -> %s", + csm->sender_ip, addr); + scheduler_session_disconnect_handler(csm); + } + } + else { + ICCPD_LOG_INFO(__FUNCTION__, "Set local-address : %s", addr); + } + + len = strlen(addr); + memset(csm->sender_ip, 0, INET_ADDRSTRLEN); + memcpy(csm->sender_ip, addr, len); + memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); + memcpy(csm->iccp_info.sender_name, addr, len); + + return 0; +} + +int unset_local_address(int mid) +{ + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + + memset(csm->sender_ip, 0, INET_ADDRSTRLEN); + memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); + + /* reset link*/ + scheduler_session_disconnect_handler(csm); + + return 0; +} + +/* +* 'peer-address A.B.C.D' command +*/ +int set_peer_address(int mid, const char* addr) +{ + struct CSM* csm = NULL; + size_t len = 0; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + if(addr == NULL) return -1; + + len = strlen(addr); + + if (strlen(csm->peer_ip) > 0) + { + if(strcmp(csm->peer_ip, addr) == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer-address not be changed"); + return 0; + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Change peer-address : %s -> %s", + csm->peer_ip, addr); + scheduler_session_disconnect_handler(csm); + } + } + else + { + ICCPD_LOG_INFO(__FUNCTION__, "Set peer-address : %s", addr); + } + + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); + memcpy(csm->peer_ip, addr, len); + + return 0; +} + +int unset_peer_address(int mid) +{ + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if(csm == NULL) return -1; + + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); + + /* reset link*/ + scheduler_session_disconnect_handler(csm); + + return 0; +} + +int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname) +{ + struct CSM* csm = NULL; + int i = 0; + int id = 0; + int len = 0; + struct LocalInterface *lif = NULL; + struct If_info * cif = NULL; + + if (!ifname) + return -1; + + if(strncmp(ifname, "Po", 2)!=0) { + ICCPD_LOG_DEBUG(__FUNCTION__, + "attach interface(%s) is not a port-channel", ifname); + return -1; + } + + csm = system_get_csm_by_mlacp_id(domain); + if (csm == NULL) { + ICCPD_LOG_DEBUG(__FUNCTION__, "MC-LAG ID %d doesn't exist", domain); + return -1; + } + + lif = local_if_find_by_name(ifname); + if (lif) + { + mlacp_bind_port_channel_to_csm(csm, ifname); + } + + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + if (strcmp(cif->name,ifname) ==0) + break; + } + + if(cif == NULL) + { + cif = (struct If_info *) malloc(sizeof(struct If_info)); + if (!cif) + return -1; + + snprintf(cif->name, MAX_L_PORT_NAME, "%s", ifname); + LIST_INSERT_HEAD(&(csm->if_bind_list), cif, csm_next); + } + + return 0; +} + +int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) +{ + int unbind_poid = -1; + struct CSM *csm = NULL; + struct LocalInterface *lif_po = NULL; + struct LocalInterface *lif = NULL; + struct If_info * cif = NULL; + + if (!ifname) + return -1; + + if (strncmp(ifname, "Po", 2)!=0) { + ICCPD_LOG_DEBUG(__FUNCTION__, + "detach interface(%s) is not a port-channel", ifname); + return -1; + } + + /* find po*/ + if (!(lif_po = local_if_find_by_name(ifname)) + || lif_po->type != IF_T_PORT_CHANNEL + || lif_po->po_id <=0 + || lif_po->csm == NULL) + { + return -1; + } + + /* find csm*/ + csm = lif_po->csm; + + ICCPD_LOG_DEBUG(__FUNCTION__, "detach mclag id = %d from ifname = %s", + csm->mlag_id, lif_po->name); + + /* process link state handler before detaching it.*/ + mlacp_mlag_link_del_handler(csm, lif_po); + + unbind_poid = lif_po->po_id; + mlacp_unbind_local_if(lif_po); + LIST_FOREACH(lif, &(csm->app_csm.mlacp.lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT && lif->po_id == unbind_poid) + mlacp_unbind_local_if(lif); + } + + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + if (strcmp(ifname, cif->name) ==0) + LIST_REMOVE(cif, csm_next); + } + return 0; +} diff --git a/src/iccpd/src/iccp_cmd.c b/src/iccpd/src/iccp_cmd.c new file mode 100644 index 000000000000..f5c17aad7d55 --- /dev/null +++ b/src/iccpd/src/iccp_cmd.c @@ -0,0 +1,160 @@ +/* +* iccp_cmd.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include + +#include "../include/iccp_csm.h" +#include "../include/msg_format.h" +#include "../include/system.h" + +#include "../include/iccp_cmd_show.h" +#include "../include/iccp_cli.h" +#include "../include/logger.h" + +int set_mc_lag_by_id(uint16_t mid) +{ + int ret = 0; + struct CSM* csm = NULL; + + csm = system_get_csm_by_mlacp_id(mid); + if (!csm) + { + csm = (struct CSM*)iccp_get_csm(); + if (csm == NULL) + { + return -1; + } + + ret = set_mc_lag_id(csm, mid); + + return ret; + } + + return ret; +} + +#define CONFIG_LINE_LEN 512 + +int iccp_config_from_command(char * line) +{ + char *cp, *start; + char token[64]; + int slen; + static int mid = 0; + char *end; + + if (line == NULL) + return 0; + + cp = line; + + /* Skip white spaces. */ + while (isspace ((int) *cp) && *cp != '\0') + cp++; + + /* Return if there is only white spaces */ + if (*cp == '\0') + return 0; + + end = cp; + + /* Skip end white spaces. */ + while (!isspace ((int) *end) && *end != '\0') + end++; + + *end = '\0'; + /*mc-lag id*/ + if (strncmp(cp,"mclag_id:",9) == 0 ) + { + cp += 9; + mid = atoi(cp); + set_mc_lag_by_id(mid); + } + else if (strncmp(cp,"local_ip:",9) == 0) /*local ip*/ + { + cp += 9; + set_local_address(mid,cp); + } + else if (strncmp(cp,"peer_ip:",8) == 0) /*peer ip*/ + { + cp += 8; + set_peer_address(mid,cp); + } + else if(strncmp(cp,"peer_link:",10) == 0) + { + cp += 10; + set_peer_link(mid,cp); + } + else if(strncmp(cp,"bind_lacp:",10) == 0) + { + cp += 10; + + while (1) + { + start = cp; + while (!(*cp == ',' || *cp == '\r' || *cp == '\n') && + *cp != '\0') + cp++; + slen = cp - start; + strncpy (token, start, slen); + *(token + slen) = '\0'; + iccp_cli_attach_mclag_domain_to_port_channel(mid, token); + + while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r' || *cp == ',') && + *cp != '\0') + cp++; + + if (*cp == '\0') + break; + } + } + else + { + /*error*/ + } + + return 1; +} + +/* Configration make from file. */ +int +iccp_config_from_file (char *config_default_dir) +{ + FILE *confp = NULL; + char command_buf[CONFIG_LINE_LEN]; + + confp = fopen (config_default_dir, "r"); + if (confp == NULL) + return (1); + + while (fgets (command_buf, CONFIG_LINE_LEN, confp)) + { + iccp_config_from_command(command_buf); + } + fclose(confp); + + return 0; +} + diff --git a/src/iccpd/src/iccp_cmd_show.c b/src/iccpd/src/iccp_cmd_show.c new file mode 100644 index 000000000000..6fae86650f11 --- /dev/null +++ b/src/iccpd/src/iccp_cmd_show.c @@ -0,0 +1,474 @@ +/* +* iccp_cmd_show.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include + +#include "../include/iccp_csm.h" +#include "../include/mlacp_tlv.h" +#include "../include/system.h" +#include "../include/logger.h" +#include "mclagdctl/mclagdctl.h" +#include "../include/mlacp_link_handler.h" +#include "../include/iccp_cmd_show.h" + +int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) +{ + struct mclagd_state state_info; + struct System *sys = NULL; + struct CSM *csm = NULL; + struct LocalInterface *peer_link_if = NULL; + struct LocalInterface *lif_po = NULL; + char unknown[] = {"UNKNOWN"}; + int mclag_num= 0; + int id_exist = 0; + char * str_buf =NULL; + int str_size =0; + int len = 0; + char *state_buf = NULL; + int state_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + state_buf = (char*)malloc(state_buf_size); + if (!state_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + memset(&state_info, 0, sizeof(struct mclagd_state)); + + if (csm->current_state == ICCP_OPERATIONAL) + state_info.keepalive = 1; + else + state_info.keepalive = 0; + + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + peer_link_if = local_if_find_by_name(csm->peer_itf_name); + + if (csm->mlag_id <= 0) + state_info.mclag_id = -1; + else + state_info.mclag_id = csm->mlag_id; + + memcpy(state_info.local_ip, csm->sender_ip, ICCP_MAX_IP_STR_LEN); + memcpy(state_info.peer_ip, csm->peer_ip, ICCP_MAX_IP_STR_LEN); + + if (peer_link_if) + memcpy(state_info.peer_link_if, peer_link_if->name, ICCP_MAX_PORT_NAME); + else + memcpy(state_info.peer_link_if, unknown, strlen(unknown)); + + if (peer_link_if) + memcpy(state_info.peer_link_mac, peer_link_if->mac_addr, 6); + + state_info.role = csm->role_type; + + str_buf = state_info.enabled_po; + str_size = MCLAGDCTL_PORT_MEMBER_BUF_LEN; + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + + if (str_size -len < ICCP_MAX_PORT_NAME) + break; + + if (lif_po->type == IF_T_PORT_CHANNEL) + len += snprintf(str_buf + len, str_size - len, "%s,", lif_po->name); + } + + memcpy(state_buf + MCLAGD_REPLY_INFO_HDR + mclag_num*sizeof(struct mclagd_state), + &state_info, sizeof(struct mclagd_state)); + + mclag_num ++; + + if ((mclag_num + 1)*sizeof(struct mclagd_state) > (state_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + state_buf_size += MCLAGDCTL_CMD_SIZE; + state_buf = (char*)realloc(state_buf, state_buf_size); + if (!state_buf) + return EXEC_TYPE_FAILED; + } + } + + *buf = state_buf; + *num = mclag_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_arp_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct ARPMsg *iccpd_arp = NULL; + struct mclagd_arp_msg mclagd_arp; + int arp_num = 0; + int id_exist = 0; + char * arp_buf = NULL; + int arp_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + arp_buf = (char*)malloc(arp_buf_size); + if (!arp_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + memset(&mclagd_arp, 0, sizeof(struct mclagd_arp_msg)); + iccpd_arp = (struct ARPMsg*)msg->buf; + + mclagd_arp.op_type = iccpd_arp->op_type; + memcpy(mclagd_arp.ifname, iccpd_arp->ifname, strlen(iccpd_arp->ifname)); + memcpy(mclagd_arp.ipv4_addr, show_ip_str(iccpd_arp->ipv4_addr), 16); + memcpy(mclagd_arp.mac_addr, iccpd_arp->mac_addr, 6); + + memcpy(arp_buf + MCLAGD_REPLY_INFO_HDR +arp_num*sizeof(struct mclagd_arp_msg), + &mclagd_arp, sizeof(struct mclagd_arp_msg)); + + arp_num ++; + + if ((arp_num + 1)*sizeof(struct mclagd_arp_msg) > (arp_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + arp_buf_size += MCLAGDCTL_CMD_SIZE; + arp_buf = (char*)realloc(arp_buf, arp_buf_size); + if (!arp_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = arp_buf; + *num = arp_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_mac_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct MACMsg *iccpd_mac = NULL; + struct mclagd_mac_msg mclagd_mac; + int mac_num = 0; + int id_exist = 0; + char * mac_buf = NULL; + int mac_buf_size = MCLAGDCTL_CMD_SIZE; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + mac_buf = (char*)malloc(mac_buf_size); + if (!mac_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + memset(&mclagd_mac, 0, sizeof(struct mclagd_mac_msg)); + iccpd_mac = (struct MACMsg*)msg->buf; + + mclagd_mac.op_type = iccpd_mac->op_type; + mclagd_mac.fdb_type = iccpd_mac->fdb_type; + memcpy(mclagd_mac.mac_str, iccpd_mac->mac_str, 32); + mclagd_mac.vid = iccpd_mac->vid; + memcpy(mclagd_mac.ifname, iccpd_mac->ifname, strlen(iccpd_mac->ifname)); + memcpy(mclagd_mac.origin_ifname, iccpd_mac->origin_ifname, strlen(iccpd_mac->origin_ifname)); + mclagd_mac.age_flag = iccpd_mac->age_flag; + + memcpy(mac_buf + MCLAGD_REPLY_INFO_HDR + mac_num*sizeof(struct mclagd_mac_msg), + &mclagd_mac, sizeof(struct mclagd_mac_msg)); + + mac_num ++; + + if ((mac_num + 1)*sizeof(struct mclagd_mac_msg) > (mac_buf_size -MCLAGD_REPLY_INFO_HDR)) + { + mac_buf_size += MCLAGDCTL_CMD_SIZE; + mac_buf = (char*)realloc(mac_buf, mac_buf_size); + if (!mac_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = mac_buf; + *num = mac_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_local_if_dump(char * *buf, int *num,int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct LocalInterface *lif_po = NULL; + struct mclagd_local_if mclagd_lif; + struct VLAN_ID* vlan_id = NULL; + char * str_buf = NULL; + int str_size = MCLAGDCTL_PARA3_LEN - 1; + int len = 0; + int lif_num = 0; + int id_exist = 0; + int lif_buf_size = MCLAGDCTL_CMD_SIZE; + char * lif_buf = NULL; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + lif_buf = (char*)malloc(lif_buf_size); + if (!lif_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + memset(&mclagd_lif, 0, sizeof(struct mclagd_local_if)); + + mclagd_lif.ifindex = lif_po->ifindex; + + if (lif_po->type == IF_T_UNKNOW) + memcpy(mclagd_lif.type, "UNKNOW", 6); + else if (lif_po->type == IF_T_PORT) + memcpy(mclagd_lif.type, "PORT", 4); + else if (lif_po->type == IF_T_PORT_CHANNEL) + memcpy(mclagd_lif.type, "PORT-CHANNEL", 12); + + memcpy(mclagd_lif.name, lif_po->name, MAX_L_PORT_NAME); + memcpy(mclagd_lif.mac_addr, lif_po->mac_addr, ETHER_ADDR_LEN); + + if (lif_po->state == PORT_STATE_UP) + memcpy(mclagd_lif.state, "UP", 2); + else if (lif_po->state == PORT_STATE_DOWN) + memcpy(mclagd_lif.state, "DOWN", 4); + else if (lif_po->state == PORT_STATE_ADMIN_DOWN) + memcpy(mclagd_lif.state, "ADMIN-DOWN", 10); + else if (lif_po->state == PORT_STATE_TEST) + memcpy(mclagd_lif.state, "TEST", 4); + + memcpy(mclagd_lif.ipv4_addr, show_ip_str(htonl(lif_po->ipv4_addr)), 16); + mclagd_lif.prefixlen = lif_po->prefixlen; + + mclagd_lif.l3_mode = local_if_is_l3_mode(lif_po); + + mclagd_lif.is_peer_link = lif_po->is_peer_link; + + memcpy(mclagd_lif.portchannel_member_buf, lif_po->portchannel_member_buf, 512); + + mclagd_lif.po_id = lif_po->po_id; + mclagd_lif.po_active = lif_po->po_active; + /*mlacp_state*/ + if (lif_po->mlacp_state == MLACP_STATE_INIT) + memcpy(mclagd_lif.mlacp_state, "INIT", 4); + else if (lif_po->mlacp_state == MLACP_STATE_STAGE1) + memcpy(mclagd_lif.mlacp_state, "STAGE1", 6); + else if (lif_po->mlacp_state == MLACP_STATE_STAGE2) + memcpy(mclagd_lif.mlacp_state, "STAGE2", 6); + else if (lif_po->mlacp_state == MLACP_STATE_EXCHANGE) + memcpy(mclagd_lif.mlacp_state, "EXCHANGE", 8); + else if (lif_po->mlacp_state == MLACP_STATE_ERROR) + memcpy(mclagd_lif.mlacp_state, "ERROR", 5); + + mclagd_lif.isolate_to_peer_link = lif_po->isolate_to_peer_link; + + str_buf = mclagd_lif.vlanlist; + + len = 0; + LIST_FOREACH(vlan_id, &(lif_po->vlan_list), port_next) + { + if (vlan_id != NULL ) + { + if (str_size -len < 4) + break; + len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid); + } + } + + memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num*sizeof(struct mclagd_local_if), + &mclagd_lif, sizeof(struct mclagd_local_if)); + + lif_num ++; + + if ((lif_num + 1)*sizeof(struct mclagd_local_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + lif_buf_size += MCLAGDCTL_CMD_SIZE; + lif_buf = (char*)realloc(lif_buf, lif_buf_size); + if (!lif_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = lif_buf; + *num = lif_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + +int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct PeerInterface *pif_po = NULL; + struct mclagd_peer_if mclagd_pif; + int pif_num = 0; + int id_exist = 0; + int pif_buf_size = MCLAGDCTL_CMD_SIZE; + char *pif_buf = NULL; + + if (!(sys = system_get_instance())) + { + ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); + return EXEC_TYPE_NO_EXIST_SYS; + } + + pif_buf = (char*)malloc(pif_buf_size); + if (!pif_buf) + return EXEC_TYPE_FAILED; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (mclag_id >0) + { + if (csm->mlag_id == mclag_id) + id_exist = 1; + else + continue; + } + + LIST_FOREACH(pif_po, &(MLACP(csm).pif_list), mlacp_next) + { + memset(&mclagd_pif, 0, sizeof(struct mclagd_peer_if)); + + mclagd_pif.ifindex = pif_po->ifindex; + + if (pif_po->type == IF_T_UNKNOW) + memcpy(mclagd_pif.type, "UNKNOW", 6); + else if (pif_po->type == IF_T_PORT) + memcpy(mclagd_pif.type, "PORT", 4); + else if (pif_po->type == IF_T_PORT_CHANNEL) + memcpy(mclagd_pif.type, "PORT-CHANNEL", 12); + + memcpy(mclagd_pif.name, pif_po->name, MAX_L_PORT_NAME); + memcpy(mclagd_pif.mac_addr, pif_po->mac_addr, ETHER_ADDR_LEN); + + if (pif_po->state == PORT_STATE_UP) + memcpy(mclagd_pif.state, "UP", 2); + else if (pif_po->state == PORT_STATE_DOWN) + memcpy(mclagd_pif.state, "DOWN", 4); + else if (pif_po->state == PORT_STATE_ADMIN_DOWN) + memcpy(mclagd_pif.state, "ADMIN-DOWN", 10); + else if (pif_po->state == PORT_STATE_TEST) + memcpy(mclagd_pif.state, "TEST", 4); + + mclagd_pif.po_id = pif_po->po_id; + mclagd_pif.po_active = pif_po->po_active; + + memcpy(pif_buf + MCLAGD_REPLY_INFO_HDR + pif_num*sizeof(struct mclagd_peer_if), + &mclagd_pif, sizeof(struct mclagd_peer_if)); + + pif_num ++; + + if ((pif_num + 1)*sizeof(struct mclagd_peer_if) > (pif_buf_size - MCLAGD_REPLY_INFO_HDR)) + { + pif_buf_size += MCLAGDCTL_CMD_SIZE; + pif_buf = (char*)realloc(pif_buf, pif_buf_size); + if (!pif_buf) + return EXEC_TYPE_FAILED; + } + } + } + + *buf = pif_buf; + *num = pif_num; + + if (mclag_id >0 && !id_exist) + return EXEC_TYPE_NO_EXIST_MCLAGID; + + return EXEC_TYPE_SUCCESS; +} + diff --git a/src/iccpd/src/iccp_consistency_check.c b/src/iccpd/src/iccp_consistency_check.c new file mode 100644 index 000000000000..da5076b4b10d --- /dev/null +++ b/src/iccpd/src/iccp_consistency_check.c @@ -0,0 +1,175 @@ +/* +* iccp_consistency_check.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +* +*/ + +#include "../include/iccp_consistency_check.h" +#include "../include/system.h" +#include "../include/port.h" +#include "../include/logger.h" + +/* Return 0 if the checking procedure is failed; otherwise, 1 (non-zero) will be returned. */ +typedef int (*ConsistencyCheckFunc)(char* ifname); + +const char *reasons[] = { + /* REASON_NONE */ + "Success", + /* REASON_INTERRFACE_MODE_IS_ASYNC */ + "Port-channel interface is not in the same mode in local and peer device, please check whether the ip addr settings is correct or not.", + /* REASON_PEER_IF_IP_IS_ASYNC */ + "IP address of peer interface is not synchronized, please check the IP address setting on the corresponding interface.", + /* REASON_PEER_IF_VLAN_IS_ASYNC */ + "VLAN settings on this port-channel interface is not synchronized, please check your configuration.", + /* REASON_MAX_ARRAY_SIZE */ + NULL +}; + +/* Consistency Checking functions */ +static int iccp_check_interface_mode( char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + struct PeerInterface* peer_if = NULL; + + local_if = local_if_find_by_name(ifname); + if(local_if == NULL) + return -2; + + csm = local_if->csm; + if(csm == NULL) + return -3; + + peer_if = peer_if_find_by_name(csm, ifname); + if(peer_if == NULL) + return -4; + + if(peer_if->l3_mode != local_if->l3_mode) + return -5; + + return 1; +} + +static int iccp_check_interface_layer3_addr(char* ifname) +{ + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + struct PeerInterface* peer_if = NULL; + + local_if = local_if_find_by_name(ifname); + if(local_if == NULL) + return -2; + + csm = local_if->csm; + if(csm == NULL) + return -3; + + peer_if = peer_if_find_by_name(csm, ifname); + if(peer_if == NULL) + return -4; + + if(peer_if->ipv4_addr != local_if->ipv4_addr) + return -5; + + return 1; +} + +static int iccp_check_interface_vlan(char* ifname) +{ + struct CSM* csm = NULL; + struct PeerInterface* peer_if = NULL; + struct VLAN_ID* local_vlan = NULL; + struct VLAN_ID* peer_vlan = NULL; + struct LocalInterface* local_if = NULL; + + local_if = local_if_find_by_name(ifname); + if(local_if == NULL) + return -2; + + csm = local_if->csm; + if(csm == NULL) + return -3; + + peer_if = peer_if_find_by_name(csm, ifname); + if(peer_if == NULL) + return -4; + + LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next) + { + LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) + { + if(peer_vlan->vid == local_vlan->vid) + break; + } + + if(peer_vlan == NULL) + { + return -5; + } + } + + LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) + { + + LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next) + { + if(peer_vlan->vid == local_vlan->vid) + break; + } + + if(local_vlan == NULL) + { + return -6; + } + } + + return 1; +} + +static const ConsistencyCheckFunc check_func[] = { + NULL, + iccp_check_interface_mode, /* REASON_INTERFACE_MODE_IS_ASYNC */ + iccp_check_interface_layer3_addr, /* REASON_PEER_IF_IP_IS_ASYNC */ + iccp_check_interface_vlan, /* REASON_PEER_IF_VLAN_IS_ASYNC */ + NULL /* REASON_MAX_ARRAY_SIZE */ +}; +#define ARRAY_SIZE(array_name) (sizeof(array_name)/sizeof(array_name[0])) + +enum Reason_ID iccp_consistency_check(char* ifname) +{ + int i = 0; + int ret = 0; + + for(i = REASON_INTERRFACE_MODE_IS_ASYNC; i < REASON_MAX_ARRAY_SIZE; ++i) + { + if(check_func[i] == NULL) + continue; + ret = check_func[i](ifname) ; + if(ret != 1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s ret = %d",reasons[i] ,ret); + fprintf(stdout,"%s \n",reasons[i]); + return i; + } + } + + return REASON_NONE; +} diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c new file mode 100644 index 000000000000..601a03c34553 --- /dev/null +++ b/src/iccpd/src/iccp_csm.c @@ -0,0 +1,746 @@ +/* +* iccp_csm.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include + +#include "../include/logger.h" +#include "../include/system.h" +#include "../include/msg_format.h" +#include "../include/mlacp_link_handler.h" + +/***************************************** +* Define +* +* ***************************************/ +#define ICCP_CSM_QUEUE_REINIT(list) \ + {\ + struct Msg* msg = NULL;\ + while (!TAILQ_EMPTY(&(list))) {\ + msg = TAILQ_FIRST(&(list));\ + TAILQ_REMOVE(&(list), msg, tail);\ + free(msg->buf);\ + free(msg);\ + }\ + TAILQ_INIT(&(list));\ + } + +/***************************************** +* Global +* +* ***************************************/ +char g_csm_buf[CSM_BUFFER_SIZE]={0}; + +uint32_t ICCP_MSG_ID = 0x1; + +/* Enter Connection State Machine NONEXISTENT handle function */ +static void iccp_csm_enter_state_nonexistent(struct CSM* csm) +{ + iccp_csm_finalize(csm); +} + +/* Enter Connection State Machine INITIALIZED handle function */ +static void iccp_csm_enter_state_initialized(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_capability_flag = 0x1; +} + +/* Enter Connection State Machine CAPREC handle function */ +static void iccp_csm_enter_state_caprec(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_capability_flag = 0x1; + csm->iccp_info.peer_capability_flag = 0x1; +} + +/* Enter Connection State Machine CONNECTING handle function */ +static void iccp_csm_enter_state_connecting(struct CSM* csm) +{ + if (csm == NULL) + return; + + csm->iccp_info.sender_rg_connect_flag = 0x1; +} + +/* Enter Connection State Machine OPERATIONAL handle function */ +static void iccp_csm_enter_state_operational(struct CSM* csm) { + if (csm == NULL) + return; + + csm->iccp_info.sender_rg_connect_flag = 0x1; + csm->iccp_info.peer_rg_connect_flag = 0x1; +} + +void *iccp_get_csm() +{ + struct CSM* csm = NULL; + struct System* sys = NULL; + + if((sys = system_get_instance()) == NULL) { + return NULL; + } + + csm = system_create_csm(); + + return csm; +} + +/* Connection State Machine instance initialization */ +void iccp_csm_init(struct CSM* csm) +{ + iccp_csm_status_reset(csm, 1); + memset(csm->sender_ip, 0, INET_ADDRSTRLEN); + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); + memset(csm->iccp_info.sender_name, 0, MAX_L_ICC_SENDER_NAME); + csm->iccp_info.icc_rg_id = 0x0; +} + +/* Connection State Machine instance status reset */ +void iccp_csm_status_reset(struct CSM* csm, int all) +{ + ICCP_CSM_QUEUE_REINIT(csm->msg_list); + + if(all) + { + bzero(csm, sizeof(struct CSM)); + ICCP_CSM_QUEUE_REINIT(csm->msg_list); + } + + csm->sock_fd = -1; + pthread_mutex_init(&csm->conn_mutex, NULL); + csm->connTimePrev = 0; + csm->heartbeat_send_time = 0; + csm->heartbeat_update_time = 0; + csm->sysid_update_time = 0; + csm->isolate_update_time = 0; + csm->role_type = STP_ROLE_NONE; + csm->sock_read_event_ptr = NULL; + csm->peer_link_if = NULL; + csm->u_msg_in_count= 0x0; + csm->i_msg_in_count = 0x0; + csm->icc_msg_in_count = 0x0; + csm->icc_msg_out_count = 0x0; + csm->iccp_info.status_code = 0x0; + csm->iccp_info.rejected_msg_id = 0x0; + csm->current_state = ICCP_NONEXISTENT; + csm->iccp_info.peer_capability_flag = 0x0; + csm->iccp_info.peer_rg_connect_flag = 0x0; + csm->iccp_info.sender_capability_flag = 0x0; + csm->iccp_info.sender_rg_connect_flag = 0x0; + app_csm_init(csm, all); + + memset(&csm->msg_log, 0, sizeof(struct MsgLog)); +} + +/* Connection State Machine instance tear down */ +void iccp_csm_finalize(struct CSM* csm) +{ + struct If_info * cif = NULL; + if (csm == NULL) + return; + + /* Clean all port block*/ + peerlink_port_isolate_cleanup(csm); + + /* Disconnect from peer */ + scheduler_session_disconnect_handler(csm); + + /* Release all Connection State Machine instance */ + app_csm_finalize(csm); + + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + LIST_REMOVE(cif, csm_next); + } + + /* Release iccp_csm */ + pthread_mutex_destroy(&(csm->conn_mutex)); + iccp_csm_msg_list_finalize(csm); + LIST_REMOVE(csm, next); + free(csm); +} + +/* Message list of Connection State Machine instance tear down */ +void iccp_csm_msg_list_finalize(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (csm == NULL) + return; + + while (!TAILQ_EMPTY(&(csm->msg_list))) + { + msg = TAILQ_FIRST(&(csm->msg_list)); + TAILQ_REMOVE(&(csm->msg_list), msg, tail); + free(msg); + } +} + +/* Send message to peer */ +int iccp_csm_send(struct CSM* csm, char* buf, int msg_len) +{ + LDPHdr* ldp_hdr = (LDPHdr*) buf; + ICCParameter* param = NULL; + + if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0) + return -1; + + if(ldp_hdr->msg_type == MSG_T_CAPABILITY) + param = (struct ICCParameter*)&buf[sizeof(LDPHdr)]; + else + param = (struct ICCParameter*)&buf[sizeof(ICCHdr)]; + + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Send(%d): len=[%d] msg_type=[%s (0x%X, 0x%X)]", csm->sock_fd, msg_len, get_tlv_type_string(param->type), ldp_hdr->msg_type, param->type);*/ + csm->msg_log.msg[csm->msg_log.end_index].msg_id = ldp_hdr->msg_id; + csm->msg_log.msg[csm->msg_log.end_index].type = ldp_hdr->msg_type; + csm->msg_log.msg[csm->msg_log.end_index].tlv = param->type; + ++csm->msg_log.end_index; + if(csm->msg_log.end_index >= 128) + csm->msg_log.end_index = 0; + + return write(csm->sock_fd, buf, msg_len); +} + +/* Connection State Machine Transition */ +void iccp_csm_transit(struct CSM* csm) +{ + int len = -1; + struct Msg* msg = NULL; + ICCP_CONNECTION_STATE_E prev_state; + + if (!csm) + return; + + prev_state = csm->current_state; + + /* No connection, but have state change? reset it...*/ + if (csm->current_state != ICCP_NONEXISTENT && csm->sock_fd <= 0) + { + csm->current_state = ICCP_NONEXISTENT; + iccp_csm_enter_state_nonexistent(csm); + return; + } + + /*if (csm->current_state != ICCP_NONEXISTENT) + ICCPD_LOG_DEBUG(__FUNCTION__, "#Begin# id:%d, fd:%d, ICCP CSM State:%d", csm->mlag_id, csm->sock_fd, csm->current_state);*/ + + msg = iccp_csm_dequeue_msg(csm); + + switch (csm->current_state) + { + case ICCP_NONEXISTENT: + scheduler_prepare_session(csm); + if (csm->sock_fd > 0 && scheduler_check_csm_config(csm) > 0) + csm->current_state = ICCP_INITIALIZED; + break; + case ICCP_INITIALIZED: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x0) + csm->current_state = ICCP_CAPSENT; + else if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x1) + csm->current_state = ICCP_CAPREC; + break; + case ICCP_CAPSENT: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x1) + csm->current_state = ICCP_CAPREC; + break; + case ICCP_CAPREC: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + if (csm->iccp_info.peer_rg_connect_flag == 0x0 && csm->iccp_info.status_code == 0x0) + csm->current_state = ICCP_CONNECTING; + else if (csm->iccp_info.peer_rg_connect_flag == 0x1 && csm->iccp_info.status_code == 0x0) + csm->current_state = ICCP_OPERATIONAL; + break; + case ICCP_CONNECTING: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + if (csm->iccp_info.status_code > 0x0) + csm->current_state = ICCP_CAPREC; + else if (csm->iccp_info.peer_rg_connect_flag == 0x1 && csm->iccp_info.status_code == 0x0) + csm->current_state = ICCP_OPERATIONAL; + break; + case ICCP_OPERATIONAL: + if (msg) + iccp_csm_correspond_from_msg(csm, msg); + if (csm->iccp_info.sender_rg_connect_flag == 0x0 || csm->iccp_info.peer_rg_connect_flag == 0x0) { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + csm->current_state = ICCP_CAPREC; + } + break; + default: + break; + } + + if (prev_state != csm->current_state || (csm->current_state && msg != NULL)) + { + ICCPD_LOG_INFO(__FUNCTION__, "csm %d enter state %d .", csm->mlag_id, csm->current_state); + + switch (csm->current_state) + { + case ICCP_NONEXISTENT: + iccp_csm_enter_state_nonexistent(csm); + break; + case ICCP_INITIALIZED: + iccp_csm_enter_state_initialized(csm); + break; + case ICCP_CAPSENT: + /* Do nothing on this state */ + break; + case ICCP_CAPREC: + iccp_csm_enter_state_caprec(csm); + break; + case ICCP_CONNECTING: + iccp_csm_enter_state_connecting(csm); + break; + case ICCP_OPERATIONAL: + iccp_csm_enter_state_operational(csm); + break; + default: + break; + } + } + /*if (csm->current_state != ICCP_NONEXISTENT && prev_state != csm->current_state) + ICCPD_LOG_DEBUG(__FUNCTION__, "#End# id:%d, fd:%d, ICCP CSM State:%d", csm->mlag_id, csm->sock_fd, csm->current_state);*/ +} + +/* Set up ICCP message */ +int iccp_csm_prepare_iccp_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + size_t msg_len = -1; + + if (csm == NULL || buf == NULL) + return -1; + + switch (csm->current_state) + { + case ICCP_NONEXISTENT: + /* Do nothing on this state */ + break; + case ICCP_INITIALIZED: + msg_len = iccp_csm_prepare_capability_msg(csm, buf, max_buf_size); + break; + case ICCP_CAPSENT: + /* Do nothing on this state */ + break; + case ICCP_CAPREC: + if (csm->iccp_info.status_code > 0x0) { + msg_len = iccp_csm_prepare_nak_msg(csm, buf, max_buf_size); + break; + } + msg_len = iccp_csm_prepare_rg_connect_msg(csm, buf, max_buf_size); + break; + case ICCP_CONNECTING: + if (csm->iccp_info.status_code > 0x0) { + msg_len = iccp_csm_prepare_nak_msg(csm, buf, max_buf_size); + break; + } + break; + case ICCP_OPERATIONAL: + if (csm->iccp_info.peer_rg_connect_flag == 0x0) { + msg_len = iccp_csm_prepare_rg_disconnect_msg(csm, buf, max_buf_size); + break; + } + break; + } + + return msg_len; +} + +/* ICCP capability message handle function */ +int iccp_csm_prepare_capability_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + LDPHdr* ldp_hdr = (LDPHdr*) buf; + LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*) &buf[sizeof(LDPHdr)]; + size_t msg_len = sizeof(LDPHdr) + sizeof(LDPICCPCapabilityTLV); + + memset(buf, 0, max_buf_size); + + /* LDP header */ + ldp_hdr->u_bit = 0x0; + ldp_hdr->msg_type = MSG_T_CAPABILITY; + ldp_hdr->msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + ldp_hdr->msg_id = ICCP_MSG_ID++; + + /* LDP ICCP capability TLV */ + cap->icc_parameter.u_bit = 0x1; + cap->icc_parameter.f_bit = 0x0; + cap->icc_parameter.type = TLV_T_ICCP_CAPABILITY; + cap->icc_parameter.len = TLV_L_ICCP_CAPABILITY; + cap->s_bit = csm->iccp_info.sender_capability_flag; + cap->major_ver = 0x1; + cap->minior_ver = 0x0; + + return msg_len; +} + +void iccp_csm_fill_icc_rg_id_tlv(struct CSM* csm, ICCHdr* icc_hdr) +{ + if (!csm || !icc_hdr) + return; + + icc_hdr->icc_rg_id_tlv.type = TLV_T_ICC_RG_ID; + icc_hdr->icc_rg_id_tlv.len = TLV_L_ICC_RG_ID; + icc_hdr->icc_rg_id_tlv.icc_rg_id = csm->iccp_info.icc_rg_id; +} + +/* ICCP NAK message handle function */ +int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + NAKTLV* nak = (NAKTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); + + memset(buf, 0, max_buf_size); + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_NOTIFICATION; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + /* NAL TLV */ + nak->icc_parameter.u_bit = 0x0; + nak->icc_parameter.f_bit = 0x0; + nak->icc_parameter.type = TLV_T_NAK; + nak->icc_parameter.len = sizeof(((struct NAKTLV*) 0)->iccp_status_code) + sizeof(((struct NAKTLV*) 0)->rejected_msg_id); + + switch (csm->iccp_info.status_code) + { + case STATUS_CODE_U_ICCP_RG: + nak->iccp_status_code = csm->iccp_info.status_code; + nak->rejected_msg_id = csm->iccp_info.rejected_msg_id; + break; + /* Unsupported */ + case STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED: + case STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED: + case STATUS_CODE_ICCP_APP_NOT_IN_RG: + case STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER: + case STATUS_CODE_ICCP_REJECTED_MSG: + case STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED: + case STATUS_CODE_ICCP_RG_REMOVED: + case STATUS_CODE_ICCP_APP_REMOVED_FROM_RG: + break; + } + + return msg_len; +} + +/* ICCP RG connect handle function */ +int iccp_csm_prepare_rg_connect_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + ICCSenderNameTLV* sender = (ICCSenderNameTLV*) &buf[sizeof(ICCHdr)]; + size_t name_len = strlen(csm->iccp_info.sender_name); + size_t msg_len = sizeof(ICCHdr) + sizeof(ICCParameter) + name_len; + + memset(buf, 0, max_buf_size); + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_RG_CONNECT; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + /* ICC sender name TLV */ + sender->icc_parameter.u_bit = 0x0; + sender->icc_parameter.f_bit = 0x0; + sender->icc_parameter.type = TLV_T_ICC_SENDER_NAME; + sender->icc_parameter.len = name_len; + memcpy(sender->sender_name, csm->iccp_info.sender_name, name_len); + + return msg_len; +} + +/* ICCP RG disconnect handle function */ +int iccp_csm_prepare_rg_disconnect_msg(struct CSM* csm, char* buf, size_t max_buf_size) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + DisconnectCodeTLV* disconn_code = (DisconnectCodeTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(DisconnectCodeTLV); + + memset(buf, 0, max_buf_size); + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_RG_DISCONNECT; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + /* Disconnect code TLV */ + disconn_code->icc_parameter.u_bit = 0x0; + disconn_code->icc_parameter.f_bit = 0x0; + disconn_code->icc_parameter.type = TLV_T_DISCONNECT_CODE; + disconn_code->icc_parameter.len = sizeof(((struct DisconnectCodeTLV*) 0)->iccp_status_code); + disconn_code->iccp_status_code = csm->iccp_info.status_code; + + return msg_len; +} + +/* Check ID(MC-LAG ID, mLACP ID, RG ID) from received message */ +static void iccp_csm_check_id_from_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + + if (!csm || !msg || !msg->buf) + return; + + icc_hdr = (ICCHdr*) msg->buf; + + /* Capability Message doesn't have ICC RG ID TLV */ + if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) + return; + + /* Check if received message ID same as local configuration */ + if (icc_hdr->icc_rg_id_tlv.icc_rg_id == csm->iccp_info.icc_rg_id) + { + if (csm->iccp_info.status_code == STATUS_CODE_U_ICCP_RG) + { + csm->iccp_info.status_code = 0x0; + csm->iccp_info.rejected_msg_id = 0x0; + } + } else if (icc_hdr->icc_rg_id_tlv.icc_rg_id != csm->iccp_info.icc_rg_id) + { + csm->iccp_info.status_code = STATUS_CODE_U_ICCP_RG; + csm->iccp_info.rejected_msg_id = icc_hdr->icc_rg_id_tlv.icc_rg_id; + } +} + +/* Receive message correspond function */ +void iccp_csm_correspond_from_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + + if (csm == NULL || msg == NULL || msg->buf == NULL) + return; + + icc_hdr = (ICCHdr*) msg->buf; + NAKTLV* nak = (NAKTLV*)( icc_hdr+sizeof(ICCHdr)); + iccp_csm_check_id_from_msg(csm, msg); + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) + iccp_csm_correspond_from_capability_msg(csm, msg); + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_CONNECT) + iccp_csm_correspond_from_rg_connect_msg(csm, msg); + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_DISCONNECT) + iccp_csm_correspond_from_rg_disconnect_msg(csm, msg); + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Received MSG_T_NOTIFICATION ,err status %s reason of %s", get_status_string(nak->iccp_status_code), get_status_string(csm->iccp_info.status_code)); + sleep(1); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + ;// do nothing + } + else + { + ++csm->u_msg_in_count; + } + + free(msg->buf); + free(msg); +} + +/* Receive capability message correspond function */ +void iccp_csm_correspond_from_capability_msg(struct CSM* csm, struct Msg* msg) +{ + LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*) &(msg->buf)[sizeof(LDPHdr)]; + + if (cap->icc_parameter.u_bit == 0x1 + && cap->icc_parameter.f_bit == 0x0 + && cap->icc_parameter.type == TLV_T_ICCP_CAPABILITY + && cap->icc_parameter.len == (TLV_L_ICCP_CAPABILITY) + && cap->s_bit == 1 + && cap->major_ver == 0x1 + && cap->minior_ver == 0x0) + { + csm->iccp_info.peer_capability_flag = 0x1; + } +} + +/* Receive RG connect message correspond function */ +void iccp_csm_correspond_from_rg_connect_msg(struct CSM* csm, struct Msg* msg) +{ + ICCSenderNameTLV* sender = (ICCSenderNameTLV*) &(msg->buf)[sizeof(ICCHdr)]; + + if (sender->icc_parameter.u_bit == 0x0 && + sender->icc_parameter.f_bit == 0x0 && + sender->icc_parameter.type == TLV_T_ICC_SENDER_NAME) + { + csm->iccp_info.peer_rg_connect_flag = 0x1; + } +} + +/* Receive RG disconnect message correspond function */ +void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM* csm, struct Msg* msg) +{ + DisconnectCodeTLV* diconn_code = (DisconnectCodeTLV*) &(msg->buf)[sizeof(ICCHdr)]; + + if (diconn_code->icc_parameter.u_bit == 0x0 + && diconn_code->icc_parameter.f_bit == 0x0 + && diconn_code->icc_parameter.type == TLV_T_DISCONNECT_CODE + && diconn_code->icc_parameter.len == (TLV_L_DISCONNECT_CODE) + && diconn_code->iccp_status_code == (STATUS_CODE_ICCP_RG_REMOVED)) + { + csm->iccp_info.sender_rg_connect_flag = 0x0; + csm->iccp_info.peer_rg_connect_flag = 0x0; + } +} + +/* Add received message into message list */ +void iccp_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + NAKTLV* naktlv = NULL; + int type = -1; + int i = 0; + + if (csm == NULL) { + if (msg != NULL) + free(msg); + return; + } + + if (msg == NULL) + return; + + icc_hdr = (ICCHdr*) msg->buf; + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + app_csm_enqueue_msg(csm, msg); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + { + naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; + + for(i=0; irejected_msg_id == csm->msg_log.msg[i].msg_id) + { + type = csm->msg_log.msg[i].type; + break; + } + } + + if(type == MSG_T_RG_APP_DATA) + app_csm_enqueue_msg(csm, msg); + else + TAILQ_INSERT_TAIL(&(csm->msg_list), msg, tail); + } + else + { + TAILQ_INSERT_TAIL(&(csm->msg_list), msg, tail); + } +} + +/* Get received message from message list */ +struct Msg* iccp_csm_dequeue_msg(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (!TAILQ_EMPTY(&(csm->msg_list))) + { + msg = TAILQ_FIRST(&(csm->msg_list)); + TAILQ_REMOVE(&(csm->msg_list), msg, tail); + + } + + return msg; +} + +/* Message initialization */ +int iccp_csm_init_msg(struct Msg** msg, char* data, int len) +{ + struct Msg* iccp_msg = NULL; + + if (msg == NULL) + return -2; + + if(data == NULL || len <= 0) + return -1; + + iccp_msg = (struct Msg*) malloc(sizeof(struct Msg)); + if (iccp_msg == NULL) + goto err_ret; + + iccp_msg->buf = (char*) malloc(len); + if (iccp_msg->buf == NULL) + goto err_ret; + + memcpy(iccp_msg->buf, data, len); + iccp_msg->len = len; + *msg = iccp_msg; + + return 0; + +err_ret: + if(iccp_msg) + { + if(iccp_msg->buf) free(iccp_msg->buf); + free(iccp_msg); + } + + return -1; +} + +void iccp_csm_stp_role_count(struct CSM *csm) +{ + /* decide the role, lower ip to be active & socket client*/ + if(csm->role_type == STP_ROLE_NONE) + { + if(inet_addr(csm->sender_ip) < inet_addr(csm->peer_ip)) + { + /* Active*/ + ICCPD_LOG_INFO(__FUNCTION__, "Role: [Active]"); + csm->role_type = STP_ROLE_ACTIVE; + } + else + { + /* Standby*/ + ICCPD_LOG_INFO(__FUNCTION__, "Role [Standby]"); + csm->role_type = STP_ROLE_STANDBY; + } + } +} \ No newline at end of file diff --git a/src/iccpd/src/iccp_ifm.c b/src/iccpd/src/iccp_ifm.c new file mode 100644 index 000000000000..4c4ec49afdee --- /dev/null +++ b/src/iccpd/src/iccp_ifm.c @@ -0,0 +1,1037 @@ +/* +* iccp_ifm.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/iccp_cli.h" +#include "../include/logger.h" +#include "../include/mlacp_sync_update.h" +#include "../include/mlacp_link_handler.h" +#include "../include/port.h" +#include "../include/iccp_netlink.h" + +#define fwd_neigh_state_valid(state) (state & (NUD_REACHABLE|NUD_STALE|NUD_DELAY|NUD_PROBE|NUD_PERMANENT)) + +#ifndef MAX_BUFSIZE + #define MAX_BUFSIZE 4096 +#endif + +#ifndef NDA_RTA +#define NDA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#endif + +static int iccp_valid_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + unsigned int event = 0; + if (nlh->nlmsg_type != RTM_NEWLINK) + return 0; + + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) + ICCPD_LOG_ERR(__FUNCTION__, "Unknown message type."); + + return 0; +} + +/*Get kernel interfaces and ports during initialization*/ +int iccp_sys_local_if_list_get_init() +{ + struct System *sys = NULL; + struct nl_cb *cb; + struct nl_cb *orig_cb; + struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, + }; + int ret; + int retry = 1; + + if (!(sys = system_get_instance())) + return -1; + + while (retry) + { + retry = 0; + ret = nl_send_simple(sys->route_sock, RTM_GETLINK, NLM_F_DUMP, + &rt_hdr, sizeof(rt_hdr)); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); + return ret; + } + + orig_cb = nl_socket_get_cb(sys->route_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + { + ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); + return -ENOMEM; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_valid_handler, sys); + + ret = nl_recvmsgs(sys->route_sock, cb); + nl_cb_put(cb); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error. ret = %d errno = %d ",ret, errno); + if (ret != -NLE_DUMP_INTR) + return ret; + retry = 1; + } + } + + return ret; +} + +/*Handle arp received from kernel*/ +static int iccp_arp_valid_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + + do_one_neigh_request(nlh); + + return 0; +} + +/*Get kernel arp information during initialization*/ +int iccp_arp_get_init() +{ + struct System *sys = NULL; + struct nl_cb *cb; + struct nl_cb *orig_cb; + struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, + }; + int ret; + int retry = 1; + + if (!(sys = system_get_instance())) + return -1; + + while (retry) + { + retry = 0; + ret = nl_send_simple(sys->route_sock, RTM_GETNEIGH, NLM_F_DUMP, + &rt_hdr, sizeof(rt_hdr)); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); + return ret; + } + + orig_cb = nl_socket_get_cb(sys->route_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + { + ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); + return -ENOMEM; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_arp_valid_handler, sys); + + ret = nl_recvmsgs(sys->route_sock, cb); + nl_cb_put(cb); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error."); + if (ret != -NLE_DUMP_INTR) + return ret; + + retry = 1; + } + } + + return ret; +} + +/*When received ARP packets from kernel, update arp information*/ +void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct ARPMsg *arp_msg = NULL, *arp_info = NULL; + struct VLAN_ID *vlan_id_list = NULL; + struct Msg *msg_send = NULL; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *arp_lif = NULL; + uint8_t mac[ETHER_ADDR_LEN]; + + struct in_addr in_addr; + int verify_arp = 0; + int arp_update = 0; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf*/ + if (!(arp_lif = local_if_find_by_ifindex(ifindex))) + return; + + /* create ARP msg*/ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct ARPMsg); + arp_msg = (struct ARPMsg*) &buf; + arp_msg->op_type = ARP_SYNC_LIF; + sprintf(arp_msg->ifname, "%s", arp_lif->name); + memcpy(&arp_msg->ipv4_addr, &addr, 4); + memcpy(arp_msg->mac_addr, mac_addr, 6); + + /*Debug*/ + #if 1 + /* dump receive kernel ARP req*/ + fprintf(stderr, "\n======== Kernel ARP Update==========\n"); + fprintf(stderr, " Type = (New=%d)\n", RTM_NEWNEIGH); + fprintf(stderr, " ifindex = [%d] (%s)\n", ifindex, arp_lif->name); + fprintf(stderr, " IP = [%s]\n", show_ip_str(arp_msg->ipv4_addr)); + fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n", + arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3], + arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + fprintf(stderr, "==============================\n"); + #endif + + /* Find MLACP itf, member of port-channel*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if (!local_if_is_l3_mode(lif_po)) + { + /* Is the L2 MLAG itf belong to a vlan?*/ + LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) + { + if ( !(vlan_id_list->vlan_itf + && vlan_id_list->vlan_itf->ifindex == ifindex)) + continue; + break; + } + + if (!vlan_id_list) continue; + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", + lif_po->name, vlan_id_list->vlan_itf->name); + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf?*/ + if (ifindex != lif_po->ifindex) continue; + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", + lif_po->name); + } + + verify_arp = 1; + + break; + } + + if (lif_po) break; + } + + if (!(csm && lif_po)) return; + if (!verify_arp) return; + + /* update lif ARP*/ + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_info = (struct ARPMsg*) msg->buf; + if (arp_info->ipv4_addr != arp_msg->ipv4_addr) + continue; + + /* update ARP*/ + if(arp_info->op_type != arp_msg->op_type + || strcmp(arp_info->ifname, arp_msg->ifname)!=0 + || strncmp(arp_info->mac_addr, arp_msg->mac_addr, + ETHER_ADDR_LEN) != 0) + { + arp_update = 1; + arp_info->op_type = arp_msg->op_type; + sprintf(arp_info->ifname, "%s", arp_msg->ifname); + memcpy(arp_info->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + time(&arp_info->update_time); + + break; + } + + /* enquene lif_msg (add)*/ + if (!msg) + { + arp_msg->op_type = ARP_SYNC_LIF; + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) + { + mlacp_enqueue_arp(csm, msg); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + arp_msg->ifname, + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + arp_msg->ifname, + show_ip_str(arp_msg->ipv4_addr)); + } + + /* enqueue iccp_msg (add)*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + arp_msg->op_type = ARP_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + + return; +} + +static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct ARPMsg *arp_msg = NULL, *arp_info = NULL; + struct VLAN_ID *vlan_id_list = NULL; + struct Msg *msg_send = NULL; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *arp_lif = NULL; + uint8_t mac[ETHER_ADDR_LEN]; + + int verify_arp = 0; + int arp_update = 0; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf*/ + if (!(arp_lif = local_if_find_by_ifindex(ndm->ndm_ifindex))) + return; + + /* create ARP msg*/ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct ARPMsg); + arp_msg = (struct ARPMsg*) &buf; + arp_msg->op_type = ARP_SYNC_LIF; + sprintf(arp_msg->ifname, "%s", arp_lif->name); + if(tb[NDA_DST]) + memcpy(&arp_msg->ipv4_addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); + if (tb[NDA_LLADDR]) + memcpy(arp_msg->mac_addr, RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR])); + + + ICCPD_LOG_DEBUG(__FUNCTION__, "arp msg type %d , state (%04X)(%d) ifindex [%d] (%s) ip %s , mac [%02X:%02X:%02X:%02X:%02X:%02X] ", + msgtype, ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), + ndm->ndm_ifindex, arp_lif->name, + show_ip_str(arp_msg->ipv4_addr), + arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3],arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + + /*Debug*/ + #if 1 + /* dump receive kernel ARP req*/ + fprintf(stderr, "\n======== Kernel ARP ==========\n"); + fprintf(stderr, " Type = [%d] (New=%d, Del=%d)\n", msgtype, RTM_NEWNEIGH, RTM_DELNEIGH); + fprintf(stderr, " State = (%04X)(%d)\n", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state)); + fprintf(stderr, " ifindex = [%d] (%s)\n", ndm->ndm_ifindex, arp_msg->ifname); + fprintf(stderr, " IP = [%s]\n", show_ip_str(arp_msg->ipv4_addr)); + fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n", + arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3], + arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + fprintf(stderr, "==============================\n"); + #endif + + /* Find MLACP itf, member of port-channel*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if (!local_if_is_l3_mode(lif_po)) + { + /* Is the L2 MLAG itf belong to a vlan?*/ + LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) + { + if ( !(vlan_id_list->vlan_itf + && vlan_id_list->vlan_itf->ifindex == ndm->ndm_ifindex)) + continue; + break; + } + + if (!vlan_id_list) continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", + lif_po->name, vlan_id_list->vlan_itf->name); + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf?*/ + if (ndm->ndm_ifindex != lif_po->ifindex) continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", + lif_po->name); + } + + verify_arp = 1; + + break; + } + + if (lif_po) break; + } + + if (!(csm && lif_po)) return; + if (!verify_arp) return; + + /* update lif ARP*/ + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_info = (struct ARPMsg*) msg->buf; + if (arp_info->ipv4_addr != arp_msg->ipv4_addr) + continue; + + if (msgtype == RTM_DELNEIGH) + { + /* delete ARP*/ + TAILQ_REMOVE(&MLACP(csm).arp_list, msg, tail); + free(msg->buf); free(msg); msg = NULL; + ICCPD_LOG_DEBUG(__FUNCTION__, "Delete ARP %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + { + /* update ARP*/ + if(arp_info->op_type != arp_msg->op_type + || strcmp(arp_info->ifname, arp_msg->ifname)!=0 + || strncmp(arp_info->mac_addr, arp_msg->mac_addr, + ETHER_ADDR_LEN) != 0) + { + arp_update = 1; + arp_info->op_type = arp_msg->op_type; + sprintf(arp_info->ifname, "%s", arp_msg->ifname); + memcpy(arp_info->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + time(&arp_info->update_time); + } + break; + } + + if (msg && !arp_update) + return; + + if (msgtype != RTM_DELNEIGH) + { + /* enquene lif_msg (add)*/ + if (!msg) + { + arp_msg->op_type = ARP_SYNC_LIF; + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) + { + mlacp_enqueue_arp(csm, msg); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + arp_msg->ifname, + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + arp_msg->ifname, + show_ip_str(arp_msg->ipv4_addr)); + } + + /* enqueue iccp_msg (add)*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + arp_msg->op_type = ARP_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + + } + } + else + { + /* enqueue iccp_msg (delete)*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + arp_msg->op_type = ARP_SYNC_DEL; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[DEL] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[DEL] for %s", + show_ip_str(arp_msg->ipv4_addr)); + + } + } + + /*Debug: dump for dequeue ARP Info*/ + #if 1 + fprintf(stderr, "\n======== ARP Info List ========\n"); + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + fprintf(stderr, "type %d,ifname %s , ip %s\n", arp_msg->op_type, arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr)); + } + fprintf(stderr, "==============================\n"); + #endif + + /*TEST dump for dequeue ARP message*/ + #if 0 + while (MLACP(csm).arp_updated && !TAILQ_EMPTY(&(MLACP(csm).arp_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); + arp_msg = (struct ARPMsg *)msg->buf; + fprintf(stderr, "\n======== Dequeue ARP ========\n"); + fprintf(stderr, " Type = [%d]\n", arp_msg->op_type); + fprintf(stderr, " State = (%04X)(%d)\n", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state)); + fprintf(stderr, " ifname = [%s]\n", arp_msg->ifname); + fprintf(stderr, " IP = [%s]\n", show_ip_str(arp_msg->ipv4_addr)); + fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n", + arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3], + arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + fprintf(stderr, "==============================\n"); + free(msg->buf); + free(msg); + } + MLACP(csm).arp_updated = 0; + #endif + + return; +} + +void ifm_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, int len) +{ + while (RTA_OK (rta, len)) + { + if (rta->rta_type <= max) + tb[rta->rta_type] = rta; + rta = RTA_NEXT (rta, len); + } +} + +int do_one_neigh_request (struct nlmsghdr *n) +{ + struct ndmsg *ndm = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr * tb[NDA_MAX+1]; + + if (n->nlmsg_type == NLMSG_DONE) + { + return 0; + } + + /* process msg_type RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH */ + if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH ) + return(0); + + len -= NLMSG_LENGTH(sizeof(*ndm)); + if (len < 0) + return -1; + + ifm_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); + + if (ndm->ndm_state == NUD_INCOMPLETE + || ndm->ndm_state == NUD_FAILED + || ndm->ndm_state == NUD_NOARP + || ndm->ndm_state == NUD_PERMANENT + || ndm->ndm_state == NUD_NONE) + { + return(0); + } + + if (!tb[NDA_DST] || ndm->ndm_type != RTN_UNICAST) + { + return(0); + } + + if (ndm->ndm_family == AF_INET) + { + do_arp_request(ndm, tb, n->nlmsg_type); + } + + return(0); +} + +/*When received MAC add and del packets from mclagsyncd, update mac information*/ +void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uint8_t fdb_type, uint8_t op_type) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct Msg *msg = NULL; + struct MACMsg *mac_msg = NULL, *mac_info = NULL; + uint8_t mac_exist = 0; + + char buf[MAX_BUFSIZE]; + size_t msg_len = 0; + + struct LocalInterface *lif_po = NULL, *mac_lif = NULL; + + if (!(sys = system_get_instance())) + return; + + /* Find local itf*/ + if (!(mac_lif = local_if_find_by_name(ifname))) + return; + + /* create MAC msg*/ + memset(buf, 0, MAX_BUFSIZE); + msg_len = sizeof(struct MACMsg); + mac_msg = (struct MACMsg*) &buf; + mac_msg->op_type = op_type; + mac_msg->fdb_type = fdb_type; + sprintf(mac_msg->mac_str, "%s", mac_str); + mac_msg->vid = vid; + sprintf(mac_msg->ifname, "%s", mac_lif->name); + sprintf(mac_msg->origin_ifname, "%s", mac_lif->name); + mac_msg->age_flag = 0; + + /*Debug*/ + #if 1 + /* dump receive MAC info*/ + fprintf(stderr, "\n======== MAC Update==========\n"); + fprintf(stderr, " MAC = %s\n", mac_str); + fprintf(stderr, " ifname = %s\n", mac_lif->name); + fprintf(stderr, " vlan id = %d\n", vid); + fprintf(stderr, " fdb type = %s\n", fdb_type==MAC_TYPE_STATIC?"static":"dynamic"); + fprintf(stderr, " op type = %s\n", op_type==MAC_SYNC_ADD?"add":"del"); + fprintf(stderr, "==============================\n"); + #endif + + /* Find MLACP itf, must be mclag enabled port-channel*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + uint8_t find = 0; + + /*If MAC is from peer-link, break; peer-link is not in MLACP(csm).lif_list*/ + if (strcmp(ifname, csm->peer_itf_name) == 0) break; + + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif_po->type != IF_T_PORT_CHANNEL) + continue; + + if(strcmp(lif_po->name, ifname) == 0) + { + find = 1; + break; + } + } + + if(find == 1) + break; + } + + if (!csm) return; + + /* find lif MAC+vid*/ + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_info = (struct MACMsg*) msg->buf; + + /*MAC and vid are equal*/ + if (strcmp(mac_info->mac_str, mac_str) == 0 && mac_info->vid== vid) + { + mac_exist = 1; + break; + } + } + + /*handle mac add*/ + if(op_type == MAC_SYNC_ADD) + { + /*same MAC exist*/ + if(mac_exist) + { + /*If the recv mac port is peer-link, that is add from iccpd, no need to handle*/ + if(strcmp(csm->peer_itf_name, mac_msg->ifname) == 0) + { + return; + } + + /*If the current mac port is peer-link, it will handle by port up event*/ + if(strcmp(csm->peer_itf_name, mac_info->ifname) == 0) + { + return; + } + + /* update MAC*/ + if(mac_info->fdb_type != mac_msg->fdb_type + || strcmp(mac_info->ifname, mac_msg->ifname) != 0 + || strcmp(mac_info->origin_ifname, mac_msg->ifname) != 0) + { + mac_info->fdb_type = mac_msg->fdb_type; + sprintf(mac_info->ifname, "%s", mac_msg->ifname); + sprintf(mac_info->origin_ifname, "%s", mac_msg->ifname); + + /*Remove MAC_AGE_LOCAL flag*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 0); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Update MAC for %s, ifname %s", mac_msg->mac_str, mac_msg->ifname); + } + else + { + /*All info are the same, Remove MAC_AGE_LOCAL flag, then return*/ + /*In theory, this will be happened that mac age and then learn*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 0); + + return; + } + } + else/*same MAC not exist*/ + { + /*If the portchannel the mac learn is change to down before the mac + sync to iccp, this mac must be deleted */ + if(mac_lif->state == PORT_STATE_DOWN) + { + del_mac_from_chip(mac_msg); + + return; + } + + /*set MAC_AGE_PEER flag before send this item to peer*/ + mac_msg->age_flag |= MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + mac_msg->op_type = MAC_SYNC_ADD; + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + struct Msg *msg_send = NULL; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, msg_len)==0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + + /*enqueue mac to mac-list*/ + if (iccp_csm_init_msg(&msg, (char*)mac_msg, msg_len)==0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); + + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-list enqueue: %s, add %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC %s, add %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + } + } + else/*handle mac del*/ + { + /*same MAC exist*/ + if(mac_exist) + { + if(strcmp(mac_info->ifname, csm->peer_itf_name) == 0) + { + /*peer-link learn mac is control by iccpd, ignore the chip del info*/ + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(peer-link), del %s vlan-id %d", + mac_info->ifname,mac_info->mac_str, mac_info->vid); + return; + } + + /*Add MAC_AGE_LOCAL flag*/ + mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 1); + + if(mac_info->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d", + mac_info->ifname,mac_info->mac_str, mac_info->vid); + + /*send mac del message to mclagsyncd.*/ + /*del_mac_from_chip(mac_info);*/ + + /*If local and peer both aged, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d, peer is not age", + mac_info->ifname,mac_info->mac_str, mac_info->vid); + + if(lif_po && lif_po->state == PORT_STATE_DOWN) + { + /*If local if is down, redirect the mac to peer-link*/ + memcpy(&mac_info->ifname, csm->peer_itf_name, IFNAMSIZ); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link", + mac_info->ifname,mac_info->mac_str, mac_info->vid); + } + + /*If local is aged but peer is not aged, Send mac add message to mclagsyncd*/ + mac_info->fdb_type = MAC_TYPE_DYNAMIC; + + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); + } + } + } + + return; +} + +void iccp_from_netlink_portchannel_state_handler( char * ifname, int state) +{ + struct CSM *csm = NULL; + struct LocalInterface *lif_po = NULL; + struct System *sys; + int po_is_active = 0; + + if((sys = system_get_instance()) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); + return; + } + + po_is_active = (state == PORT_STATE_UP); + + /* traverse all CSM */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if(lif_po->type == IF_T_PORT_CHANNEL && strncmp(lif_po->name, ifname, MAX_L_PORT_NAME) == 0) + { + mlacp_portchannel_state_handler(csm,lif_po,po_is_active); + } + } + } + /*peerlink state is sync by heardbeat, do not need to response */ + + return; +} + +int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, + int len, unsigned short flags) +{ + unsigned short type; + + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + + while (RTA_OK(rta, len)) + { + type = rta->rta_type & ~flags; + if ((type <= max) && (!tb[type])) + tb[type] = rta; + rta = RTA_NEXT(rta,len); + } + + return 0; +} + +int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) +{ + return parse_rtattr_flags(tb, max, rta, len, 0); +} + +void iccp_get_if_vlan_info_from_netlink() +{ + struct LocalInterface *lif = NULL; + struct { + struct nlmsghdr nlh; + struct ifinfomsg ifm; + /* attribute has to be NLMSG aligned */ + struct rtattr ext_req __attribute__ ((aligned(NLMSG_ALIGNTO))); + __u32 ext_filter_mask; + } req; + + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char * buf = malloc(10000000); + struct nl_sock *sk ; + int fd; + + struct System *sys; + + if((sys = system_get_instance()) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); + free(buf); + return; + } + fd = nl_socket_get_fd(sys->route_sock); + + memset(&req, 0, sizeof(req)); + req.nlh.nlmsg_len = sizeof(req); + req.nlh.nlmsg_type = RTM_GETLINK; + req.nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = 0; + req.ifm.ifi_family = PF_BRIDGE; + + req.ext_req.rta_type = IFLA_EXT_MASK; + req.ext_req.rta_len = RTA_LENGTH(sizeof(__u32)); + req.ext_filter_mask = RTEXT_FILTER_BRVLAN; + + send(fd, (void*)&req, sizeof(req), 0); + + iov.iov_base = buf; + while (1) + { + int status; + int msglen = 0; + + iov.iov_len = 10000000; + + status = recvmsg(fd, &msg, 0); + + if (status < 0 ||status == 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "netlink receive error (%d) status %d %d ", fd, status,errno); + free(buf); + return ; + } + + struct nlmsghdr *n = (struct nlmsghdr*)buf; + + msglen = status; + + while (NLMSG_OK(n, msglen)) + { + + struct ifinfomsg *ifm = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr * tb[IFLA_MAX+1]; + + if (n->nlmsg_type != RTM_NEWLINK) + { + free(buf); + return ; + } + + len -= NLMSG_LENGTH(sizeof(*ifm)); + if (len < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "BUG: wrong nlmsg len %d\n", len); + free(buf); + return ; + } + + if (ifm->ifi_family != AF_BRIDGE) + { + free(buf); + return ; + } + + if (lif = local_if_find_by_ifindex(ifm->ifi_index)) + { + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len); + + /* if AF_SPEC isn't there, vlan table is not preset for this port */ + if (!tb[IFLA_AF_SPEC]) + { + ICCPD_LOG_WARN(__FUNCTION__, "%d None\n", (ifm->ifi_index)); + free(buf); + return ; + } + else + { + struct rtattr *i, *list = tb[IFLA_AF_SPEC]; + int rem = RTA_PAYLOAD(list); + struct VLAN_ID *vlan = NULL; + + /*set vlan flag is removed*/ + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + vlan->vlan_removed = 1; + } + + for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) + { + struct bridge_vlan_info *vinfo; + + if (i->rta_type != IFLA_BRIDGE_VLAN_INFO) + continue; + + vinfo = RTA_DATA(i); + + local_if_add_vlan(lif, vinfo->vid); + + /*ICCPD_LOG_DEBUG(__FUNCTION__, "get vlan netlink msg lif index %d vinfo->flag %d, vid %d",ifm->ifi_index, vinfo->flags, vinfo->vid ); */ + } + + /*After update vlan list, remove unused item*/ + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if(vlan->vlan_removed == 1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Delete VLAN ID = %d from %s", vlan->vid, lif->name); + + LIST_REMOVE(vlan, port_next); + free(vlan); + } + } + } + } + + n = NLMSG_NEXT(n, msglen); + } + } + free(buf); +} + diff --git a/src/iccpd/src/iccp_main.c b/src/iccpd/src/iccp_main.c new file mode 100644 index 000000000000..f5a4fff3f275 --- /dev/null +++ b/src/iccpd/src/iccp_main.c @@ -0,0 +1,186 @@ +/* +* iccp_main.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include + +#include "../include/cmd_option.h" +#include "../include/logger.h" +#include "../include/scheduler.h" +#include "../include/system.h" + +int check_instance(char* pid_file_path) +{ + int pid_file = 0; + int rc = 0; + + if (pid_file_path == NULL) + return -1; + + pid_file = open(pid_file_path, O_CREAT | O_RDWR, 0666); + if(pid_file <=0 ) + { + fprintf(stderr, "Can't open a pid file. Terminate.\n"); + close(pid_file); + exit(EXIT_FAILURE); + } + + rc = flock(pid_file, LOCK_EX | LOCK_NB); + + if (rc) + { + if (errno == EWOULDBLOCK) + { + fprintf(stderr, "There is another instance running. Terminate.\n"); + close(pid_file); + exit(EXIT_FAILURE); + } + } + + return pid_file; +} + +void init_daemon(char* pid_file_path, int pid_file) +{ + pid_t pid, sid; + + pid = fork(); + if (pid < 0) + { + fprintf(stderr, "Failed to enter daemon mode: %s\n", strerror(errno)); + fprintf(stderr, "Please try to check your system resources.\n"); + close(pid_file); + unlink(pid_file_path); + exit(EXIT_FAILURE); + } + + if (pid > 0) + exit(EXIT_SUCCESS); + + umask(0); + sid = setsid(); + if (sid < 0) + { + fprintf(stderr, "Failed to create a new SID for this program: %s\n", strerror(errno)); + fprintf(stderr, "Please try to check your system resources.\n"); + close(pid_file); + unlink(pid_file_path); + exit(EXIT_FAILURE); + } + + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); +} + +#ifndef ICCPD_RUN_DIR +#define ICCPD_RUN_DIR "/var/run/iccpd/" +#endif + +static inline int iccpd_make_rundir(void) +{ + int ret; + + ret = mkdir(ICCPD_RUN_DIR, 0755); + if (ret && errno != EEXIST) + { + ICCPD_LOG_ERR(__FUNCTION__,"Failed to create directory \"%s\"", + ICCPD_RUN_DIR); + + return -errno; + } + + return 0; +} + +int main(int argc, char* argv[]) +{ + char *p; + int pid_file_fd = 0; + struct System* sys = NULL; + int err; + struct CmdOptionParser parser = CMD_OPTION_PARSER_INIT_VALUE; + + err = iccpd_make_rundir(); + if (err) + return 0; + + if (getuid() != 0) + { + fprintf(stderr, + "This program needs root permission to do device manipulation. " + "Please use sudo to execute it or change your user to root.\n"); + exit(EXIT_FAILURE); + } + + parser.init(&parser); + if (parser.parse(&parser, argc, argv) != 0) + { + parser.finalize(&parser); + return -1; + } + + pid_file_fd = check_instance(parser.pid_file_path); + if (pid_file_fd < 0) + { + fprintf(stderr, "Check instance with invalidate arguments, iccpd is terminated.\n"); + parser.finalize(&parser); + exit(EXIT_FAILURE); + } + + sys = system_get_instance(); + if (!sys) + { + fprintf(stderr, "Can't get a system instance, iccpd is terminated.\n"); + parser.finalize(&parser); + exit(EXIT_FAILURE); + } + + /*if(!parser.console_log) + init_daemon(parser.pid_file_path, pid_file_fd);*/ + + log_init(&parser); + + if (sys->log_file_path != NULL) + free(sys->log_file_path); + if (sys->cmd_file_path != NULL) + free(sys->cmd_file_path); + if (sys->config_file_path != NULL) + free(sys->config_file_path); + sys->log_file_path = strdup(parser.log_file_path); + sys->cmd_file_path = strdup(parser.cmd_file_path); + sys->config_file_path = strdup(parser.config_file_path); + sys->mclagdctl_file_path = strdup(parser.mclagdctl_file_path); + sys->pid_file_fd = pid_file_fd; + sys->telnet_port = parser.telnet_port; + parser.finalize(&parser); + + ICCPD_LOG_INFO(__FUNCTION__, "Iccpd is started, process id = %d.", getpid()); + scheduler_init(); + scheduler_start(); + scheduler_finalize(); + system_finalize(); + log_finalize(); + + return EXIT_SUCCESS; +} diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c new file mode 100644 index 000000000000..9f21bf0d5dfb --- /dev/null +++ b/src/iccpd/src/iccp_netlink.c @@ -0,0 +1,1136 @@ +/* +* iccp_netlink.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/iccp_ifm.h" +#include "../include/port.h" +#include "../include/iccp_csm.h" +#include "../include/logger.h" +#include "../include/scheduler.h" + +/** + * SECTION: Netlink helpers + */ + /* \cond HIDDEN_SYMBOLS */ +#ifndef SOL_NETLINK +#define SOL_NETLINK 270 +#endif + +#define ARRAY_SIZE(array_name) (sizeof(array_name)/sizeof(array_name[0])) + +#ifndef NETLINK_BROADCAST_SEND_ERROR +#define NETLINK_BROADCAST_SEND_ERROR 0x4 +#endif + +static int iccp_ack_handler(struct nl_msg *msg, void *arg) +{ + bool *acked = arg; + + *acked = true; + + return NL_STOP; +} + +static int iccp_seq_check_handler(struct nl_msg *msg, void *arg) +{ + unsigned int *seq = arg; + struct nlmsghdr *hdr = nlmsg_hdr(msg); + + if (hdr->nlmsg_seq != *seq) + return NL_SKIP; + + return NL_OK; +} + +int iccp_send_and_recv(struct System *sys, struct nl_msg *msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) +{ + int ret; + struct nl_cb *cb; + struct nl_cb *orig_cb; + bool acked; + unsigned int seq = sys->genric_sock_seq++; + int err; + + ret = nl_send_auto(sys->genric_sock, msg); + nlmsg_free(msg); + if (ret < 0) + return ret; + + orig_cb = nl_socket_get_cb(sys->genric_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + return -ENOMEM; + + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, iccp_ack_handler, &acked); + nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, iccp_seq_check_handler, &seq); + if (valid_handler) + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); + + /* There is a bug in libnl. When implicit sequence number checking is in + * use the expected next number is increased when NLMSG_DONE is + * received. The ACK which comes after that correctly includes the + * original sequence number. However libnl is checking that number + * against the incremented one and therefore ack handler is never called + * and nl_recvmsgs finished with an error. To resolve this, custom + * sequence number checking is used here. + */ + + acked = false; + while (!acked) + { + ret = nl_recvmsgs(sys->genric_sock, cb); + if (ret) + { + err = ret; + goto put_cb; + } + } + + err = 0; +put_cb: + nl_cb_put(cb); + return err; +} + +int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, struct LocalInterface* local_if) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct nlattr *attrs[TEAM_ATTR_MAX + 1]; + struct nlattr *nl_port; + struct nlattr *port_attrs[TEAM_ATTR_PORT_MAX + 1]; + struct LocalInterface* lif = NULL; + struct LocalInterface* local_if_member = NULL; + struct CSM* csm; + int i; + uint32_t ifindex = 0; + struct System* sys = NULL; + char temp_buf[512]; + int len = 0; + + sys = system_get_instance(); + if (sys == NULL) + return 0; + + genlmsg_parse(nlh, 0, attrs, TEAM_ATTR_MAX, NULL); + + if (attrs[TEAM_ATTR_TEAM_IFINDEX]) + ifindex = nla_get_u32(attrs[TEAM_ATTR_TEAM_IFINDEX]); + + if(local_if == NULL) + local_if = local_if_find_by_ifindex(ifindex); + + if (!local_if) + return NL_SKIP; + + if (local_if->type != IF_T_PORT_CHANNEL) + return NL_SKIP; + + csm = local_if->csm; + + if(csm) + { + if (!attrs[TEAM_ATTR_LIST_PORT]) + return NL_SKIP; + + nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) + { + uint32_t member_index; + + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to parse nested attributes."); + return NL_SKIP; + } + + if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) + { + ICCPD_LOG_ERR(__FUNCTION__, "ifindex port attribute not found."); + return NL_SKIP; + } + + member_index = nla_get_u32(port_attrs[TEAM_ATTR_PORT_IFINDEX]); + + local_if_member = local_if_find_by_ifindex(member_index); + if(local_if_member == NULL) + { + + ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance (%d).", + local_if->name, member_index); + sys->need_sync_team_again = 1; + continue; + } + + if(port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) + { + local_if_member->po_id = -1; + mlacp_unbind_local_if(local_if_member); + } + else if ( local_if_member->po_id == -1) + { + local_if_member->po_id = local_if->po_id; + mlacp_bind_local_if(local_if->csm, local_if_member); + } + } + + memset(temp_buf, 0, 512); + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) + { + if(strlen(temp_buf) != 0) + len += snprintf(temp_buf + len, 512-len,"%s", ","); + + len += snprintf(temp_buf + len, 512-len,"%s",lif->name); + } + } + + if(strcmp(temp_buf,local_if->portchannel_member_buf)) + { + memset(local_if->portchannel_member_buf, 0, 512); + memcpy(local_if->portchannel_member_buf,temp_buf,sizeof(local_if->portchannel_member_buf)-1); + + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /* portchannel member changed, update port isolate attribute*/ + /*update_peerlink_isolate_from_all_csm_lif(csm); */ + csm->isolate_update_time = time(NULL); + } + } + } + else /*peerlink portchannel */ + { + if(local_if->is_peer_link) + { + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm->peer_link_if == local_if ) + { + break; + } + } + + if (csm == NULL) + return 0; + + nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) + { + uint32_t member_index; + + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to parse nested attributes."); + return NL_SKIP; + } + + if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) + { + ICCPD_LOG_WARN(__FUNCTION__, "ifindex port attribute not found."); + return NL_SKIP; + } + + member_index = nla_get_u32(port_attrs[TEAM_ATTR_PORT_IFINDEX]); + + local_if_member = local_if_find_by_ifindex(member_index); + if(local_if_member == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance (%d).", + local_if->name, member_index); + sys->need_sync_team_again = 1; + continue; + } + + if(port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) + { + local_if_member->po_id = -1; + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*link removed from portchannel, must be enabled mac learn*/ + set_peerlink_mlag_port_learn(local_if_member, 1); + } + + continue; + } + else if ( local_if_member->po_id == -1) + { + local_if_member->po_id = local_if->po_id; + + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*link add to portchannel, must be disabled mac learn*/ + set_peerlink_mlag_port_learn(local_if, 0); + } + } + } + + memset(temp_buf, 0, 512); + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) + { + if(strlen(temp_buf) != 0) + len += snprintf(temp_buf + len, 512-len,"%s", ","); + + len += snprintf(temp_buf + len, 512-len,"%s",lif->name); + } + } + + if(strcmp(temp_buf,local_if->portchannel_member_buf)) + { + memset(local_if->portchannel_member_buf, 0, 512); + memcpy(local_if->portchannel_member_buf,temp_buf,sizeof(local_if->portchannel_member_buf)-1); + + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*peerlink portchannel member changed*/ + /*update_peerlink_isolate_from_all_csm_lif(csm);*/ + csm->isolate_update_time = time(NULL); + } + } + } + } + + return 0; +} + +int iccp_get_port_member_list(struct LocalInterface* lif) +{ + struct System *sys; + struct nl_msg *msg; + int err; + + sys = system_get_instance(); + if(sys == NULL) + return 0; + + msg = nlmsg_alloc(); + if (!msg) + return -ENOMEM; + + genlmsg_put(msg, NL_AUTO_PID, sys->genric_sock_seq, sys->family, 0, 0, + TEAM_CMD_PORT_LIST_GET, 0); + nla_put_u32(msg, TEAM_ATTR_TEAM_IFINDEX, lif->ifindex); + + err = iccp_send_and_recv(sys, msg, iccp_get_portchannel_member_list_handler, lif); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "recv msg err err = %d . errno = %d", err , errno); + return err; + } + + return 0; +} + +void update_local_system_id(struct LocalInterface* local_if) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if((sys = system_get_instance()) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); + return; + } + + if (local_if->type != IF_T_PORT_CHANNEL && local_if->po_id == -1) + return; + + /* traverse all CSM */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + /* sync system info from one port-channel device*/ + if(memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0 || + memcmp(MLACP(csm).remote_system.system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) + { + memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); + MLACP(csm).system_config_changed = 1; + + update_system_id(csm); + ICCPD_LOG_INFO(__FUNCTION__, + "update csm %d local system id to mac %02x:%02x:%02x:%02x:%02x:%02x of %s ", csm->mlag_id, local_if->mac_addr[0],local_if->mac_addr[1], + local_if->mac_addr[2],local_if->mac_addr[3],local_if->mac_addr[4],local_if->mac_addr[5], local_if->name ); + } + } + + return; +} + +void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link; + unsigned int *event = arg; + uint32_t ifindex; + char * ifname; + struct LocalInterface *lif = NULL; + struct nl_addr *nl_addr; + int addr_type = 0; + int op_state = 0; + + link = (struct rtnl_link *) obj; + ifindex = rtnl_link_get_ifindex(link); + op_state = rtnl_link_get_operstate(link); + ifname = rtnl_link_get_name(link); + nl_addr = rtnl_link_get_addr(link); + + if (nl_addr) + addr_type = nl_addr_guess_family(nl_addr); + + lif = local_if_find_by_ifindex(ifindex); + + if (!lif) + { + const itf_type_t if_whitelist[] = { + {"Po",IF_T_PORT_CHANNEL}, + {"Vl", IF_T_VLAN}, + {"Eth", IF_T_PORT}, + {NULL, 0} }; + int i = 0; + + for (i = 0; if_whitelist[i].ifname != NULL ; ++i) + { + if ((strncmp(ifname, + if_whitelist[i].ifname, strlen(if_whitelist[i].ifname)) == 0)) + { + lif = local_if_create(ifindex, ifname, if_whitelist[i].type); + + + lif->state = PORT_STATE_DOWN; + + if(IF_OPER_UP == op_state ) + { + lif->state = PORT_STATE_UP; + } + + switch (addr_type) + { + case AF_LLC: + memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); + update_local_system_id(lif); + default: + break; + } + + break; + } + } + } + else /*update*/ + { + /*update*/ + if(lif->state == PORT_STATE_DOWN && op_state == IF_OPER_UP) + { + lif->state = PORT_STATE_UP; + if(lif->type ==IF_T_PORT_CHANNEL) + iccp_from_netlink_portchannel_state_handler(lif->name, lif->state); + + ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); + } + else if (lif->state == PORT_STATE_UP && IF_OPER_UP != op_state) + { + lif->state = PORT_STATE_DOWN; + if(lif->type ==IF_T_PORT_CHANNEL) + iccp_from_netlink_portchannel_state_handler(lif->name, lif->state); + + ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); + } + + switch (addr_type) + { + case AF_LLC: + if (memcmp(nl_addr_get_binary_addr(nl_addr), lif->mac_addr, ETHER_ADDR_LEN) != 0) + { + memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); + lif->port_config_sync = 1; + + update_local_system_id(lif); + } + default: + break; + } + + /*sync port vlan info from kernel */ + if(lif && lif->type ==IF_T_PORT_CHANNEL && (*event)) + iccp_get_if_vlan_info_from_netlink(); + } + + return; +} + +void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) +{ + struct rtnl_link *link; + struct LocalInterface *lif; + uint32_t ifindex; + + link = (struct rtnl_link *) obj; + + ifindex = rtnl_link_get_ifindex(link); + if ((lif = local_if_find_by_ifindex(ifindex))) + local_if_destroy(lif->name); + + return; +} + + int iccp_local_if_addr_update(struct nl_msg *msg) + { + int len; + struct ifaddrmsg *ifa; + struct rtattr *tb[IFA_MAX + 1]; + struct LocalInterface *lif; + + struct nlmsghdr *n = nlmsg_hdr(msg); + + if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) + return 0; + + ifa = NLMSG_DATA (n); + + if (ifa->ifa_family != AF_INET ) + return 0; + + lif = local_if_find_by_ifindex(ifa->ifa_index); + if (!lif) + { + return 0; + } + + if (n->nlmsg_type == RTM_DELADDR) + { + lif->ipv4_addr = 0; + lif->prefixlen = 0; + lif->l3_mode = 0; + } + + len = n->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg)); + if (len < 0) + return 0; + + struct rtattr *rth = IFA_RTA(ifa); + int rtl = IFA_PAYLOAD(n); + + while (rtl && RTA_OK(rth, rtl)) + { + if (rth->rta_type == IFA_ADDRESS) + { + uint32_t ipaddr = htonl(*((uint32_t *)RTA_DATA(rth))); + lif->ipv4_addr = ipaddr; + lif->prefixlen = ifa->ifa_prefixlen; + lif->l3_mode = 1; + ICCPD_LOG_DEBUG(__FUNCTION__," if name %s index %d address %d.%d.%d.%d\n", + lif->name, + ifa->ifa_index , + (ipaddr >> 24) & 0xff, + (ipaddr >> 16) & 0xff, + (ipaddr >> 8) & 0xff, + ipaddr & 0xff); + } + rth = RTA_NEXT(rth, rtl); + } + + return 0; + } + + int iccp_sys_local_if_list_get_addr() +{ + struct System *sys = NULL; + struct nl_cb *cb; + struct nl_cb *orig_cb; + struct rtgenmsg rt_hdr = { + .rtgen_family = AF_UNSPEC, + }; + int ret; + int retry = 1; + + if (!(sys = system_get_instance())) + return -1; + + while (retry) + { + retry = 0; + ret = nl_send_simple(sys->route_sock, RTM_GETADDR, NLM_F_DUMP, + &rt_hdr, sizeof(rt_hdr)); + + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); + return ret; + } + + orig_cb = nl_socket_get_cb(sys->route_sock); + cb = nl_cb_clone(orig_cb); + nl_cb_put(orig_cb); + if (!cb) + { + ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); + return -ENOMEM; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_local_if_addr_update, sys); + ret = nl_recvmsgs(sys->route_sock, cb); + nl_cb_put(cb); + if (ret < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error ret = %d errno = %d .", ret, errno); + if (ret != -NLE_DUMP_INTR) + return ret; + retry = 1; + } + } + + return ret; +} + +static int iccp_route_event_handler(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + unsigned int event = 1; + + switch (nlh->nlmsg_type) + { + case RTM_NEWLINK: + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type."); + break; + case RTM_DELLINK: + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_dellink, NULL) < 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type."); + break; + case RTM_NEWNEIGH: + case RTM_DELNEIGH: + do_one_neigh_request(nlh); + break; + case RTM_NEWADDR: + iccp_local_if_addr_update(msg); + break; + + default: + return NL_OK; + } + + return NL_STOP; +} + +/** + * SECTION: Context functions + */ +static int iccp_genric_event_handler(struct nl_msg *msg, void *arg) +{ + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + + switch (gnlh->cmd) + { + case TEAM_CMD_PORT_LIST_GET: + return iccp_get_portchannel_member_list_handler(msg, NULL); + } + + return NL_SKIP; +} + +/*init netlink socket*/ +int iccp_system_init_netlink_socket() +{ + struct System* sys = NULL; + int val = 0; + int grp_id = 0; + int err = 0; + int log_err_period = 0, log_err_time = 0; + + if ((sys = system_get_instance()) == NULL ) + return -1; + + sys->genric_sock = nl_socket_alloc(); + if (!sys->genric_sock) + goto err_genric_sock_alloc; + + sys->genric_sock_seq = time(NULL); + err = genl_connect(sys->genric_sock); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sock sys->genric_sock."); + goto err_genric_sock_connect; + } + + sys->genric_event_sock = nl_socket_alloc(); + if (!sys->genric_event_sock) + goto err_genric_event_sock_alloc; + + err = genl_connect(sys->genric_event_sock); + if(err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->genric_event_sock."); + goto err_genric_event_sock_connect; + } + + sys->route_sock = nl_cli_alloc_socket(); + if (!sys->route_sock) + goto err_route_sock_alloc; + err = nl_cli_connect(sys->route_sock, NETLINK_ROUTE); + if (err) + goto err_route_sock_connect; + + sys->route_event_sock = nl_socket_alloc(); + if (!sys->route_event_sock) + goto err_route_event_sock_alloc; + + err = nl_connect(sys->route_event_sock, NETLINK_ROUTE); + if(err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->route_event_sock. "); + goto err_route_event_sock_connect; + } + + err = nl_socket_set_buffer_size(sys->route_event_sock, 98304, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink route event sock."); + goto err_route_event_sock_connect; + } + + val = NETLINK_BROADCAST_SEND_ERROR; + err = setsockopt(nl_socket_get_fd(sys->genric_event_sock), SOL_NETLINK, + NETLINK_BROADCAST_ERROR, &val, sizeof(val)); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed set NETLINK_BROADCAST_ERROR on netlink event sock."); + goto err_return; + } + + err = nl_socket_set_buffer_size(sys->genric_sock, 98304, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink sock."); + goto err_return; + } + + err = nl_socket_set_buffer_size(sys->genric_event_sock, 98304, 0); + if (err) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink event sock."); + goto err_return; + } + + sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + while (sys->family < 0) + { + sleep(1); + log_err_period++; + /*If no portchannel configuration, teamd will not started, genl_ctrl_resolve() will return <0 forever */ + /*Only log error message 5 times*/ + if(log_err_period == 1 && log_err_time < 5) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink family. %d of TEAM_GENL_NAME %s ", sys->family, TEAM_GENL_NAME); + log_err_time++; + } + else + { + /*Log error message every 30s per time*/ + if(log_err_period == 30) + log_err_period = 0; + } + + sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + } + + grp_id = genl_ctrl_resolve_grp(sys->genric_sock, TEAM_GENL_NAME, + TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME); + if (grp_id < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink multicast groups. %d", grp_id); + goto err_return; + } + + err = nl_socket_add_membership(sys->genric_event_sock, grp_id); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + nl_socket_disable_seq_check(sys->genric_event_sock); + nl_socket_modify_cb(sys->genric_event_sock, NL_CB_VALID, NL_CB_CUSTOM, + iccp_genric_event_handler, sys); + + nl_socket_disable_seq_check(sys->route_event_sock); + nl_socket_modify_cb(sys->route_event_sock, NL_CB_VALID, NL_CB_CUSTOM, + iccp_route_event_handler, sys); + + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_NEIGH); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_LINK); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_IPV4_IFADDR); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + goto err_return; + } + + /*receive arp packet socket*/ + sys->arp_receive_fd = socket(PF_PACKET, SOCK_DGRAM, 0); + if (sys->arp_receive_fd < 0) + { + ICCPD_LOG_ERR(__FUNCTION__,"socket error "); + goto err_return; + } + + if (1) + { + struct sockaddr_ll sll; + memset(&sll, 0, sizeof(sll)); + sll.sll_family = AF_PACKET; + sll.sll_protocol = htons(ETH_P_ARP); + sll.sll_ifindex = 0; + if (bind(sys->arp_receive_fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) + { + ICCPD_LOG_ERR(__FUNCTION__,"socket bind error"); + goto err_return; + } + } + + goto succes_return; + +err_return: + +err_route_event_sock_connect: + nl_socket_free(sys->route_event_sock); + +err_route_sock_alloc: +err_route_sock_connect: + nl_socket_free(sys->route_sock); + +err_route_event_sock_alloc: +err_genric_event_sock_connect: + nl_socket_free(sys->genric_event_sock); + +err_genric_event_sock_alloc: +err_genric_sock_connect: + nl_socket_free(sys->genric_sock); + + return err; + +err_genric_sock_alloc: + +succes_return: + return 0; +} + +static int iccp_get_netlink_genic_sock_event_fd(struct System *sys) +{ + return nl_socket_get_fd(sys->genric_event_sock); +} + +static int iccp_netlink_genic_sock_event_handler(struct System *sys) +{ + int ret = 0; + + ret = nl_recvmsgs_default(sys->genric_event_sock); + if(ret) + { + sys->need_sync_team_again = 1; + ICCPD_LOG_DEBUG(__FUNCTION__, "genric_event_sock %d recvmsg error ret = %d ",nl_socket_get_fd(sys->genric_event_sock), ret); + } + + return ret; +} + +static int iccp_get_netlink_route_sock_event_fd(struct System *sys) +{ + return nl_socket_get_fd(sys->route_event_sock); +} + +static int iccp_get_receive_arp_packet_sock_fd(struct System *sys) +{ + return sys->arp_receive_fd; +} + +static int iccp_receive_arp_packet_handler(struct System *sys) +{ + unsigned char buf[1024]; + struct sockaddr_ll sll; + socklen_t sll_len = sizeof(sll); + struct arphdr *a = (struct arphdr*)buf; + int n; + unsigned int ifindex; + unsigned int addr; + uint8_t mac_addr[ETHER_ADDR_LEN]; + + n = recvfrom(sys->arp_receive_fd, buf, sizeof(buf), MSG_DONTWAIT, + (struct sockaddr*)&sll, &sll_len); + if (n < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "arp recvfrom: %s",buf); + return -1; + } + + /* Sanity checks */ + if (n < sizeof(*a) || + (a->ar_op != htons(ARPOP_REQUEST) && + a->ar_op != htons(ARPOP_REPLY)) || + a->ar_pln != 4 || + a->ar_pro != htons(ETH_P_IP) || + a->ar_hln != sll.sll_halen || + sizeof(*a) + 2*4 + 2*a->ar_hln > n) + return -1; + + /*Only process ARPOP_REPLY*/ + if(a->ar_op == htons(ARPOP_REQUEST)) + return 0; + + ifindex = sll.sll_ifindex; + memcpy(mac_addr, (char*)(a+1), 6); + memcpy(&addr, (char*)(a+1) + a->ar_hln, 4); + + do_arp_update (ifindex, addr, mac_addr); + + return 0; +} + +static int iccp_netlink_route_sock_event_handler(struct System *sys) +{ + int ret = 0; + + ret = nl_recvmsgs_default(sys->route_event_sock); + + if(ret) + { + sys->need_sync_netlink_again = 1; + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d recvmsg error ret = %d errno = %d ",nl_socket_get_fd(sys->route_event_sock), ret, errno); + } + + return ret; +} + +void iccp_netlink_sync_again() +{ + struct System* sys = NULL; + struct LocalInterface* lif = NULL; + + if ((sys = system_get_instance()) == NULL ) + return ; + + if(sys->need_sync_netlink_again) + { + sys->need_sync_netlink_again = 0; + + /*Get kernel interface and port */ + iccp_sys_local_if_list_get_init(); + } + + if(sys->need_sync_team_again) + { + sys->need_sync_team_again = 0; + + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->type == IF_T_PORT_CHANNEL) + { + iccp_get_port_member_list(lif); + } + } + } + + return; +} + +extern int iccp_get_receive_fdb_sock_fd(struct System *sys); +extern int iccp_receive_fdb_handler_from_syncd(struct System *sys); + +/* cond HIDDEN_SYMBOLS */ +struct iccp_eventfd { + int (*get_fd)(struct System* sys); + int (*event_handler)(struct System* sys); +}; +/* endcond */ + +static const struct iccp_eventfd iccp_eventfds[] = { + { + .get_fd = iccp_get_server_sock_fd, + .event_handler = scheduler_server_accept, + }, + { + .get_fd = iccp_get_netlink_genic_sock_event_fd, + .event_handler = iccp_netlink_genic_sock_event_handler, + }, + { + .get_fd = iccp_get_netlink_route_sock_event_fd, + .event_handler = iccp_netlink_route_sock_event_handler, + }, + { + .get_fd = iccp_get_receive_arp_packet_sock_fd, + .event_handler = iccp_receive_arp_packet_handler, + } +}; + +/* \cond HIDDEN_SYMBOLS */ +#define ICCP_EVENT_FDS_COUNT ARRAY_SIZE(iccp_eventfds) +/* \endcond */ +/* +@return fd. + * + **/ + +int iccp_get_eventfd_fd(struct System *sys) +{ + return sys->epoll_fd; +} + +int iccp_init_netlink_event_fd(struct System *sys) +{ + int efd; + int i; + struct epoll_event event; + int err; + + efd = epoll_create1(0); + if (efd == -1) + return -errno; + for (i = 0; i < ICCP_EVENT_FDS_COUNT; i++) + { + int fd = iccp_eventfds[i].get_fd(sys); + + event.data.fd = fd; + event.events = EPOLLIN; + err = epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event); + if (err == -1) + { + err = -errno; + goto close_efd; + } + } + + sys->epoll_fd = efd; + + return 0; + +close_efd: + close(efd); + + return err; +} + +/** + * + * @details Handler events which happened on event filedescriptor. + * + * @return Zero on success or negative number in case of an error. + **/ + +int iccp_handle_events(struct System * sys) +{ + struct epoll_event events[ICCP_EVENT_FDS_COUNT+sys->readfd_count]; + struct CSM* csm = NULL; + int nfds; + int n; + int i; + int err; + int max_nfds; + max_nfds = ICCP_EVENT_FDS_COUNT+sys->readfd_count; + + nfds = epoll_wait(sys->epoll_fd, events, max_nfds, EPOLL_TIMEOUT_MSEC); + + /* Go over list of event fds and handle them sequentially */ + for (i = 0; i < nfds; i++) + { + for (n = 0; n < ICCP_EVENT_FDS_COUNT; n++) + { + const struct iccp_eventfd *eventfd = &iccp_eventfds[n]; + if (events[i].data.fd == eventfd->get_fd(sys)) + { + err = eventfd->event_handler(sys); + if (err) + ICCPD_LOG_INFO(__FUNCTION__, "Scheduler fd %d handler error %d !",events[i].data.fd, err ); + break; + } + } + + if (n < ICCP_EVENT_FDS_COUNT) + continue; + + if (events[i].data.fd == sys->sync_ctrl_fd) + { + int client_fd = mclagd_ctl_sock_accept(sys->sync_ctrl_fd); + if (client_fd > 0) + { + mclagd_ctl_interactive_process(client_fd); + close(client_fd); + } + continue; + } + + if (events[i].data.fd == sys->sync_fd) + { + iccp_receive_fdb_handler_from_syncd(sys); + + continue; + } + + if (FD_ISSET(events[i].data.fd, &sys->readfd)) + { + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm->sock_fd == events[i].data.fd ) + { + scheduler_csm_read_callback(csm); + break; + } + } + } + } + + return 0; +} + diff --git a/src/iccpd/src/logger.c b/src/iccpd/src/logger.c new file mode 100644 index 000000000000..c495b3452ebb --- /dev/null +++ b/src/iccpd/src/logger.c @@ -0,0 +1,124 @@ +/* +* logger.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ +#include +#include +#include +#include + +#include "../include/cmd_option.h" +#include "../include/logger.h" + +static uint32_t _iccpd_log_level_map[] = +{ + LOG_DEBUG, + LOG_INFO, + LOG_NOTICE, + LOG_WARNING, + LOG_ERR, + LOG_CRIT, +}; + +static char* log_level_to_string(int level) +{ + switch (level) + { + case CRITICAL_LOG_LEVEL: + return "CRITICAL"; + case ERR_LOG_LEVEL: + return "ERROR"; + case WARN_LOG_LEVEL: + return "WARN"; + case NOTICE_LOG_LEVEL: + return "NOTICE"; + case INFO_LOG_LEVEL: + return "INFO"; + case DEBUG_LOG_LEVEL: + return "DEBUG"; + } + + return "INFO"; +} + +struct LoggerConfig* logger_get_configuration() +{ + static struct LoggerConfig config; + + if (config.init == 0) + { + config.console_log_enabled = 0; + config.log_level = DEBUG_LOG_LEVEL; + config.init = 1; + } + + return &config; +} + +void log_init(struct CmdOptionParser* parser) +{ + struct LoggerConfig* config = logger_get_configuration(); + config->console_log_enabled = parser->console_log; +} + +void log_finalize() +{ + /*do nothing*/ +} + +void write_log(const int level, const char* tag, const char* format, ...) +{ + struct LoggerConfig* config = logger_get_configuration(); + char buf[LOGBUF_SIZE]; + va_list args; + unsigned int prefix_len; + unsigned int avbl_buf_len; + unsigned int print_len; + +#if 0 + if (!config->console_log_enabled) + return; +#endif + + if (level < config->log_level) + return; + + prefix_len = snprintf(buf, LOGBUF_SIZE, "[%s.%s] ", tag, log_level_to_string(level)); + avbl_buf_len = LOGBUF_SIZE - prefix_len; + + va_start(args, format); + print_len = vsnprintf(buf + prefix_len, avbl_buf_len, format, args); + va_end(args); + + /* Since osal_vsnprintf doesn't always return the exact size written to the buffer, + * we must check if the user string length exceeds the remaing buffer size. + */ + if (print_len > avbl_buf_len) + { + print_len = avbl_buf_len; + } + + buf[prefix_len+print_len] = '\0'; + ICCPD_UTILS_SYSLOG(_iccpd_log_level_map[level], "%s", buf); + + return; +} + diff --git a/src/iccpd/src/mclagdctl/Makefile b/src/iccpd/src/mclagdctl/Makefile new file mode 100644 index 000000000000..5520da22cee2 --- /dev/null +++ b/src/iccpd/src/mclagdctl/Makefile @@ -0,0 +1,28 @@ + + +C = gcc +SOURCES = \ +mclagdctl.c + +OBJECTS = \ +mclagdctl.o + +HEADERS = \ +mclagdctl.h + +CFLAGS = -g -O2 -fstack-protector-strong -Wformat -Werror=format-security +LDFLAGS = +LDADD = + +all: mclagdctl + +%.o: %.c $(HEADERS) + +mclagdctl: $(OBJECTS) + $(CC) -o ./mclagdctl $(OBJECTS) $(LDFLAGS) + +.PHONY: clean +clean: + -rm -f $(OBJECTS) ./mclagdctl + + diff --git a/src/iccpd/src/mclagdctl/mclagdctl.c b/src/iccpd/src/mclagdctl/mclagdctl.c new file mode 100644 index 000000000000..d6da3b9f4b79 --- /dev/null +++ b/src/iccpd/src/mclagdctl/mclagdctl.c @@ -0,0 +1,792 @@ +/* + /* Copyright(c) 2016-2019 Nephos. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: Jim Jiang from nephos +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mclagdctl.h" + +static int mclagdctl_sock_fd = -1; +char *mclagdctl_sock_path = "/var/run/iccpd/mclagdctl.sock"; + +/* +Already implemented command: +mclagdctl -i dump state +mclagdctl -i dump arp +mclagdctl -i dump mac +mclagdctl -i dump portlist local +mclagdctl -i dump portlist peer +*/ + +static struct command_type command_types[] = +{ + { + .id = ID_CMDTYPE_D, + .name = "dump", + .enca_msg = NULL, + .parse_msg = NULL, + }, + { + .id = ID_CMDTYPE_D_S, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_STATE, + .name = "state", + .enca_msg = mclagdctl_enca_dump_state, + .parse_msg = mclagdctl_parse_dump_state, + }, + { + .id = ID_CMDTYPE_D_A, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_ARP, + .name = "arp", + .enca_msg = mclagdctl_enca_dump_arp, + .parse_msg = mclagdctl_parse_dump_arp, + }, + { + .id = ID_CMDTYPE_D_A, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_MAC, + .name = "mac", + .enca_msg = mclagdctl_enca_dump_mac, + .parse_msg = mclagdctl_parse_dump_mac, + }, + { + .id = ID_CMDTYPE_D_P, + .parent_id = ID_CMDTYPE_D, + .name = "portlist", + }, + { + .id = ID_CMDTYPE_D_P_L, + .parent_id = ID_CMDTYPE_D_P, + .info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST, + .name = "local", + .enca_msg = mclagdctl_enca_dump_local_portlist, + .parse_msg = mclagdctl_parse_dump_local_portlist, + }, + { + .id = ID_CMDTYPE_D_P_P, + .parent_id = ID_CMDTYPE_D_P, + .info_type = INFO_TYPE_DUMP_PEER_PORTLIST, + .name = "peer", + .enca_msg = mclagdctl_enca_dump_peer_portlist, + .parse_msg = mclagdctl_parse_dump_peer_portlist, + }, +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define COMMAND_TYPE_COUNT ARRAY_SIZE(command_types) + +int mclagdctl_sock_connect() +{ + struct sockaddr_un addr; + int addrlen = 0; + int ret = 0; + + if(mclagdctl_sock_fd >= 0) + return 0; + + if(strlen(mclagdctl_sock_path) <= 0) + return -1; + + mclagdctl_sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); + + if(mclagdctl_sock_fd < 0) + { + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "%s", mclagdctl_sock_path); + addrlen = sizeof(addr.sun_family) + strlen(mclagdctl_sock_path); + + if((ret = connect(mclagdctl_sock_fd, (struct sockaddr*)&addr, addrlen)) < 0) + { + close(mclagdctl_sock_fd); + mclagdctl_sock_fd = -1; + return -1; + } + + return 0; +} + +void mclagdctl_sock_close() +{ + if(mclagdctl_sock_fd > 0) + { + close(mclagdctl_sock_fd); + mclagdctl_sock_fd = -1; + } + + return; +} + +int mclagdctl_sock_write(int fd, unsigned char *w_buf ,int total_len) +{ + int write_len =0; + int ret=0; + + while(write_len < total_len) + { + ret = write(fd, w_buf + write_len, total_len - write_len); + if(ret <= 0) + { + return 0; + } + write_len += ret; + } + + return write_len; +} + +int mclagdctl_sock_read(int fd, unsigned char *r_buf ,int total_len) +{ + int read_len=0; + int ret=0; + struct timeval tv = {0}; + fd_set read_fd; + + while(read_len < total_len) + { + FD_ZERO(&read_fd); + FD_SET(fd, &read_fd); + tv.tv_sec = 10; + tv.tv_usec = 0; + + switch ((ret = select(fd + 1, &read_fd, NULL, NULL, &tv))) + { + case -1:// error + fprintf(stdout, "Mclagdctl:Select return error:%s\n", strerror(errno)); + return -1; + case 0:// timeout + fprintf(stdout, "Mclagdctl:Select timeout:%s\n", strerror(errno)); + return -1; + default: + break; + } + + ret = read(fd, r_buf + read_len, total_len - read_len); + if(ret <= 0) + { + return -1; + } + read_len += ret; + } + + return read_len; +} + +int mclagdctl_enca_dump_state(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_STATE; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_state(char *msg, int data_len) +{ + struct mclagd_state * state_info = NULL; + int len = 0; + int count = 0; + int pos = 0; + + len = sizeof (struct mclagd_state); + + for (; data_len >= len; data_len -=len, count ++) + { + state_info = (struct mclagd_state*)(msg + len * count); + + fprintf(stdout,"%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR"); + + if (state_info->mclag_id <= 0) + fprintf(stdout,"%s: %s\n", "Mclag id", "UNKNOWN"); + else + fprintf(stdout,"%s: %d\n" ,"Mclag id", state_info->mclag_id); + + fprintf(stdout,"%s: %s\n", "Local Ip", state_info->local_ip); + fprintf(stdout,"%s: %s\n", "Peer Ip", state_info->peer_ip); + fprintf(stdout,"%s: %s\n", "Peer Link Interface", state_info->peer_link_if); + + fprintf(stdout,"%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "Peer Link Mac", + state_info->peer_link_mac[0], state_info->peer_link_mac[1], + state_info->peer_link_mac[2], state_info->peer_link_mac[3], + state_info->peer_link_mac[4], state_info->peer_link_mac[5]); + + if (state_info->role == 0) + fprintf(stdout,"%s: %s\n", "Role", "NONE"); + else if (state_info->role == 1) + fprintf(stdout,"%s: %s\n", "Role", "ACTIVE"); + else if (state_info->role == 2) + fprintf(stdout,"%s: %s\n", "Role", "STANDBY"); + + fprintf(stdout,"%s: %s\n", "Enabled PortChannel", state_info->enabled_po); + + } + + return 0; +} + +int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return -1; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_ARP; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_arp(char *msg, int data_len) +{ + struct mclagd_arp_msg * arp_info = NULL; + int len = 0; + int count = 0; + + fprintf(stdout, "%-6s", "No."); + fprintf(stdout, "%-20s", "IP"); + fprintf(stdout, "%-20s", "MAC"); + fprintf(stdout, "%-20s", "DEV"); + fprintf(stdout, "\n"); + + len = sizeof (struct mclagd_arp_msg); + + for (; data_len >= len; data_len -=len, count ++) + { + arp_info = (struct mclagd_arp_msg*)(msg + len * count); + + fprintf(stdout, "%-6d", count+1); + fprintf(stdout, "%-20s", arp_info->ipv4_addr); + fprintf(stdout,"%02x:%02x:%02x:%02x:%02x:%02x", + arp_info->mac_addr[0], arp_info->mac_addr[1], + arp_info->mac_addr[2], arp_info->mac_addr[3], + arp_info->mac_addr[4], arp_info->mac_addr[5]); + fprintf(stdout, " "); + fprintf(stdout, "%-20s", arp_info->ifname); + fprintf(stdout, "\n"); + } + + return 0; +} + +int mclagdctl_enca_dump_mac(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return -1; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_MAC; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_mac(char *msg, int data_len) +{ + struct mclagd_mac_msg * mac_info = NULL; + int len = 0; + int count = 0; + + fprintf(stdout, "%-60s\n", "TYPE: S-STATIC, D-DYNAMIC; AGE: L-Local age, P-Peer age"); + + fprintf(stdout, "%-6s", "No."); + fprintf(stdout, "%-5s", "TYPE"); + fprintf(stdout, "%-20s", "MAC"); + fprintf(stdout, "%-5s", "VID"); + fprintf(stdout, "%-20s", "DEV"); + fprintf(stdout, "%-20s", "ORIGIN-DEV"); + fprintf(stdout, "%-5s", "AGE"); + fprintf(stdout, "\n"); + + len = sizeof (struct mclagd_mac_msg); + + for (; data_len >= len; data_len -=len, count ++) + { + mac_info = (struct mclagd_mac_msg*)(msg + len * count); + + fprintf(stdout, "%-6d", count + 1); + + if(mac_info->fdb_type == MAC_TYPE_STATIC_CTL) + fprintf(stdout, "%-5s", "S"); + else + fprintf(stdout, "%-5s", "D"); + + fprintf(stdout, "%-20s", mac_info->mac_str); + fprintf(stdout, "%-5d", mac_info->vid); + fprintf(stdout, "%-20s", mac_info->ifname); + fprintf(stdout, "%-20s", mac_info->origin_ifname); + + if((mac_info->age_flag & MAC_AGE_LOCAL_CTL) && (mac_info->age_flag & MAC_AGE_PEER_CTL)) + fprintf(stdout, "%-5s", "LP"); + else if(mac_info->age_flag & MAC_AGE_LOCAL_CTL) + fprintf(stdout, "%-5s", "L"); + else if(mac_info->age_flag & MAC_AGE_PEER_CTL) + fprintf(stdout, "%-5s", "P"); + else + fprintf(stdout, "%-5s", " "); + fprintf(stdout, "\n"); + } + + return 0; +} + +int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return -1; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_local_portlist(char *msg, int data_len) +{ + struct mclagd_local_if * lif_info = NULL; + int len = 0; + int count = 0; + int pos = 0; + + len = sizeof (struct mclagd_local_if); + + for (; data_len >= len; data_len -=len, count ++) + { + lif_info = (struct mclagd_local_if*)(msg + len * count); + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + fprintf(stdout, "\n"); + + if (memcmp(lif_info->type, "PORT-CHANNEL", 12) == 0) + { + fprintf(stdout,"%s: %d\n" ,"Ifindex", lif_info->ifindex); + fprintf(stdout,"%s: %s\n", "Type", lif_info->type); + fprintf(stdout,"%s: %s\n", "PortName", lif_info->name); + fprintf(stdout,"%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "MAC", + lif_info->mac_addr[0], lif_info->mac_addr[1], + lif_info->mac_addr[2], lif_info->mac_addr[3], + lif_info->mac_addr[4], lif_info->mac_addr[5]); + + fprintf(stdout,"%s: %s\n", "IPv4Address", lif_info->ipv4_addr); + fprintf(stdout,"%s: %d\n" ,"Prefixlen", lif_info->prefixlen); + fprintf(stdout,"%s: %s\n", "State", lif_info->state); + fprintf(stdout,"%s: %d\n" ,"L3Mode", lif_info->l3_mode); + fprintf(stdout,"%s: %d\n" ,"IsPeerlink", lif_info->is_peer_link); + fprintf(stdout,"%s: %s\n", "PortchannelMem", lif_info->portchannel_member_buf); + fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); + fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", lif_info->po_active); + fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state); + fprintf(stdout,"%s: %d\n" ,"IsIsolateWithPeerlink", lif_info->isolate_to_peer_link); + fprintf(stdout,"%s: %s\n" ,"VlanList", lif_info->vlanlist); + } + else + { + fprintf(stdout,"%s: %d\n" ,"Ifindex", lif_info->ifindex); + fprintf(stdout,"%s: %s\n", "Type", lif_info->type); + fprintf(stdout,"%s: %s\n", "PortName", lif_info->name); + fprintf(stdout,"%s: %s\n", "State", lif_info->state); + fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); + } + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + + fprintf(stdout, "\n\n"); + } + + return 0; +} + +int mclagdctl_enca_dump_peer_portlist(char *msg, int mclag_id, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + if (mclag_id <= 0) + { + fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); + return -1; + } + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_DUMP_PEER_PORTLIST; + req.mclag_id = mclag_id; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len) +{ + struct mclagd_peer_if * pif_info = NULL; + int len = 0; + int count = 0; + int pos = 0; + + len = sizeof (struct mclagd_peer_if); + + for (; data_len >= len; data_len -=len, count ++) + { + pif_info = (struct mclagd_peer_if*)(msg + len * count); + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + fprintf(stdout, "\n"); + + fprintf(stdout,"%s: %d\n" ,"Ifindex", pif_info->ifindex); + fprintf(stdout,"%s: %s\n", "Type", pif_info->type); + fprintf(stdout,"%s: %s\n", "PortName", pif_info->name); + fprintf(stdout,"%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "MAC", + pif_info->mac_addr[0], pif_info->mac_addr[1], + pif_info->mac_addr[2], pif_info->mac_addr[3], + pif_info->mac_addr[4], pif_info->mac_addr[5]); + + fprintf(stdout,"%s: %s\n", "State", pif_info->state); + fprintf(stdout,"%s: %d\n" ,"PortchannelId", pif_info->po_id); + fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", pif_info->po_active); + + for (pos = 0; pos < 60; ++pos) + fprintf(stdout, "-"); + + fprintf(stdout, "\n\n"); + } + + return 0; +} + +static bool __mclagdctl_cmd_executable(struct command_type *cmd_type) +{ + if (!cmd_type->enca_msg || !cmd_type->parse_msg) + return 0; + + return 1; +} + +static int __mclagdctl_cmd_param_cnt(struct command_type *cmd_type) +{ + int i = 0; + while (cmd_type->params[i]) + i++; + + return i; +} + +static struct command_type *__mclagdctl_get_cmd_by_parent(char *cmd_name, + enum id_command_type parent_id) +{ + int i; + + for (i = 0; i < COMMAND_TYPE_COUNT; i++) + { + if (!strncmp(command_types[i].name, cmd_name, strlen(cmd_name)) + && command_types[i].parent_id == parent_id) + return &command_types[i]; + } + + return NULL; +} + +static struct command_type *__mclagdctl_get_cmd_by_id(enum id_command_type id) +{ + int i; + + for (i = 0; i < COMMAND_TYPE_COUNT; i++) + { + if (command_types[i].id == id) + return &command_types[i]; + } + + return NULL; +} + +static int mclagdctl_find_cmd(struct command_type **pcmd_type, int *argc, char ***argv) +{ + char *cmd_name; + enum id_command_type parent_id = ID_CMDTYPE_NONE; + struct command_type *cmd_type; + + while (1) + { + if (!*argc) + { + fprintf(stderr, "None or incomplete command\n"); + return -EINVAL; + } + + cmd_name = *argv[0]; + (*argc)--; + (*argv)++; + cmd_type = __mclagdctl_get_cmd_by_parent(cmd_name, parent_id); + + if (!cmd_type) + { + fprintf(stderr, "Unknown command \"%s\".\n", cmd_name); + return -EINVAL; + } + + if (__mclagdctl_cmd_executable(cmd_type) && __mclagdctl_cmd_param_cnt(cmd_type) >= *argc) + { + *pcmd_type = cmd_type; + return 0; + } + + parent_id = cmd_type->id; + } +} + +static int mclagdctl_check_cmd_params(struct command_type *cmd_type, + int argc, char **argv) +{ + int i = 0; + + while (cmd_type->params[i]) + { + if (i == argc) + { + fprintf(stderr, "Command line parameter \"%s\" expected.\n", cmd_type->params[i]); + return -EINVAL; + } + i++; + } + return 0; +} + +static void mclagdctl_print_cmd(struct command_type *cmd_type) +{ + if (cmd_type->parent_id != ID_CMDTYPE_NONE) { + mclagdctl_print_cmd(__mclagdctl_get_cmd_by_id(cmd_type->parent_id)); + fprintf(stdout, " "); + } + fprintf(stdout, "%s", cmd_type->name); +} + +static void mclagdctl_print_help(const char *argv0) +{ + int i, j; + struct command_type *cmd_type; + + fprintf(stdout, "%s [options] command [command args]\n" + " -h --help Show this help\n" + " -i --mclag-id Specify one mclag id\n", + argv0); + fprintf(stdout, "Commands:\n"); + for (i = 0; i < COMMAND_TYPE_COUNT; i++) + { + cmd_type = &command_types[i]; + if (!__mclagdctl_cmd_executable(cmd_type)) + continue; + fprintf(stdout, " "); + mclagdctl_print_cmd(cmd_type); + for (j = 0; cmd_type->params[j]; j++) + fprintf(stdout, " %s", cmd_type->params[j]); + fprintf(stdout, "\n"); + } +} + +int main(int argc, char **argv) +{ + char buf[MCLAGDCTL_CMD_SIZE]= {0}; + char *argv0 = argv[0]; + char *rcv_buf = NULL; + static const struct option long_options[] = + { + { "help", no_argument, NULL, 'h' }, + { "mclag id", required_argument, NULL, 'i' }, + { NULL, 0, NULL, 0 } + }; + int opt; + int err; + struct command_type *cmd_type; + int ret; + unsigned mclag_id = 0; + int len = 0; + char *data; + struct mclagd_reply_hdr *reply; + + while ((opt = getopt_long(argc, argv, "hi:", long_options, NULL)) >= 0) + { + switch(opt) + { + case 'h': + mclagdctl_print_help(argv0); + return EXIT_SUCCESS; + case 'i': + mclag_id = atoi (optarg); + break; + case '?': + fprintf(stderr, "unknown option.\n"); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + default: + fprintf(stderr, "unknown option \"%c\".\n", opt); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + } + + argv += optind; + argc -= optind; + + err = mclagdctl_find_cmd(&cmd_type, &argc, &argv); + if (err) + { + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + + err = mclagdctl_check_cmd_params(cmd_type, argc, argv); + if (err) + { + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + + if (mclagdctl_sock_fd <= 0) + { + ret = mclagdctl_sock_connect(); + if(ret < 0) + return EXIT_FAILURE; + } + + if (cmd_type->enca_msg(buf, mclag_id, argc, argv) < 0) + { + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + ret = mclagdctl_sock_write(mclagdctl_sock_fd, buf, sizeof(struct mclagdctl_req_hdr)); + + if(ret <= 0) + { + fprintf(stderr, "Failed to send command to mclagd\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + /*read data length*/ + memset(buf, 0, MCLAGDCTL_CMD_SIZE); + ret = mclagdctl_sock_read(mclagdctl_sock_fd, buf, sizeof(int)); + if(ret <= 0) + { + fprintf(stderr, "Failed to read data length from mclagd\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + /*cont length*/ + len = *((int*)buf); + if(len <= 0) + { + ret = EXIT_FAILURE; + fprintf(stderr, "pkt len = %d, error\n", len); + goto mclagdctl_disconnect; + } + + rcv_buf = (char *)malloc(len); + if (!rcv_buf) + { + fprintf(stderr, "Failed to malloc rcv_buf for mclagdctl\n"); + goto mclagdctl_disconnect; + } + + /*read data*/ + ret = mclagdctl_sock_read(mclagdctl_sock_fd, rcv_buf, len); + if(ret <= 0) + { + fprintf(stderr, "Failed to read data from mclagd\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + reply = (struct mclagd_reply_hdr *)rcv_buf; + + if (reply->info_type != cmd_type->info_type) + { + fprintf(stderr, "Reply info type from mclagd error\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + if (reply->exec_result == EXEC_TYPE_NO_EXIST_SYS) + { + fprintf(stderr, "No exist sys in iccpd!\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + if (reply->exec_result == EXEC_TYPE_NO_EXIST_MCLAGID) + { + fprintf(stderr, "Mclag-id %d hasn't been configured in iccpd!\n", mclag_id); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + if (reply->exec_result == EXEC_TYPE_FAILED) + { + fprintf(stderr, "exec error in iccpd!\n"); + ret = EXIT_FAILURE; + goto mclagdctl_disconnect; + } + + cmd_type->parse_msg((char *)(rcv_buf + sizeof(struct mclagd_reply_hdr)), len - sizeof(struct mclagd_reply_hdr)); + + ret = EXIT_SUCCESS; + +mclagdctl_disconnect: + mclagdctl_sock_close(); + + if (rcv_buf) + free(rcv_buf); + + return ret; +} + diff --git a/src/iccpd/src/mclagdctl/mclagdctl.h b/src/iccpd/src/mclagdctl/mclagdctl.h new file mode 100644 index 000000000000..4219bff4e588 --- /dev/null +++ b/src/iccpd/src/mclagdctl/mclagdctl.h @@ -0,0 +1,177 @@ +/* Copyright(c) 2016-2019 Nephos. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: Jim Jiang from nephos +*/ + +#define MCLAGDCTL_PARA1_LEN 16 +#define MCLAGDCTL_PARA2_LEN 32 +#define MCLAGDCTL_PARA3_LEN 64 +#define MCLAGDCTL_CMD_SIZE 4096 + +#define MCLAGDCTL_MAX_L_PORT_NANE 32 +#define MCLAGDCTL_INET_ADDR_LEN 32 +#define MCLAGDCTL_ETHER_ADDR_LEN 6 +#define MCLAGDCTL_PORT_MEMBER_BUF_LEN 512 + +typedef int (*call_enca_msg_fun)(char *msg, int mclag_id, int argc, char **argv); +typedef int (*call_parse_msg_fun)(char *msg, int data_len); + +enum MAC_TYPE_CTL { + MAC_TYPE_STATIC_CTL = 1, + MAC_TYPE_DYNAMIC_CTL = 2, +}; + +enum MAC_AGE_TYPE_CTL { + MAC_AGE_LOCAL_CTL = 1,/*MAC in local switch is ageout*/ + MAC_AGE_PEER_CTL = 2/*MAC in peer switch is ageout*/ +}; + +enum id_command_type +{ + ID_CMDTYPE_NONE = 0, + ID_CMDTYPE_D, + ID_CMDTYPE_D_S, + ID_CMDTYPE_D_A, + ID_CMDTYPE_D_P, + ID_CMDTYPE_D_P_L, + ID_CMDTYPE_D_P_P, +}; + +enum mclagdctl_notify_peer_type +{ + INFO_TYPE_NONE = 0, + INFO_TYPE_DUMP_STATE, + INFO_TYPE_DUMP_ARP, + INFO_TYPE_DUMP_MAC, + INFO_TYPE_DUMP_LOCAL_PORTLIST, + INFO_TYPE_DUMP_PEER_PORTLIST, + INFO_TYPE_FINISH, +}; + +struct mclagdctl_req_hdr +{ + int info_type; + int mclag_id; + char para1[MCLAGDCTL_PARA2_LEN]; + char para2[MCLAGDCTL_PARA2_LEN]; + char para3[MCLAGDCTL_PARA2_LEN]; +}; + +struct mclagd_reply_hdr +{ + int info_type; + int data_len; + int exec_result; +}; + +#define EXEC_TYPE_SUCCESS -1 +#define EXEC_TYPE_NO_EXIST_SYS -2 +#define EXEC_TYPE_NO_EXIST_MCLAGID -3 +#define EXEC_TYPE_FAILED -4 + +#define MCLAGD_REPLY_INFO_HDR (sizeof(struct mclagd_reply_hdr) + sizeof(int)) + +#define MCLAGDCTL_COMMAND_PARAM_MAX_CNT 8 +struct command_type +{ + enum id_command_type id; + enum id_command_type parent_id; + enum mclagdctl_notify_peer_type info_type; + char *name; + char *params[MCLAGDCTL_COMMAND_PARAM_MAX_CNT]; + call_enca_msg_fun enca_msg; + call_parse_msg_fun parse_msg; +}; + +struct mclagd_state +{ + int mclag_id; + int keepalive; + unsigned char local_ip[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char peer_ip[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char peer_link_if[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char peer_link_mac[MCLAGDCTL_ETHER_ADDR_LEN]; + int role; + unsigned char enabled_po[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; +}; + +struct mclagd_arp_msg +{ + unsigned char op_type; + unsigned char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; +}; + +struct mclagd_mac_msg +{ + unsigned char op_type;/*add or del*/ + unsigned char fdb_type;/*static or dynamic*/ + char mac_str[32]; + unsigned short vid; + /*Current if name that set in chip*/ + char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + /*if we set the mac to peer-link, origin_ifname store the + original if name that learned from chip*/ + char origin_ifname[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char age_flag;/*local or peer is age?*/ +}; + +struct mclagd_local_if +{ + int ifindex; + unsigned char type[MCLAGDCTL_PARA1_LEN]; + unsigned char name[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; + unsigned char state[MCLAGDCTL_PARA1_LEN]; + unsigned char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN]; + unsigned char prefixlen; + + unsigned char l3_mode; + unsigned char is_peer_link; + unsigned char portchannel_member_buf[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; + int po_id; /* Port Channel ID */ + unsigned char po_active; + unsigned char mlacp_state[MCLAGDCTL_PARA1_LEN]; + unsigned char isolate_to_peer_link; + + unsigned char vlanlist[MCLAGDCTL_PARA3_LEN]; +}; + +struct mclagd_peer_if +{ + int ifindex; + unsigned char type[MCLAGDCTL_PARA1_LEN]; + unsigned char name[MCLAGDCTL_MAX_L_PORT_NANE]; + unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; + unsigned char state[MCLAGDCTL_PARA1_LEN]; + int po_id; + unsigned char po_active; +}; + +extern int mclagdctl_enca_dump_state(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_state(char *msg, int data_len); +extern int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_arp(char *msg, int data_len); +extern int mclagdctl_enca_dump_mac(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_mac(char *msg, int data_len); +extern int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_local_portlist(char *msg, int data_len); +extern int mclagdctl_enca_dump_peer_portlist(char *msg, int mclag_id, int argc, char **argv); +extern int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len); + diff --git a/src/iccpd/src/mclagdctl/mclagdctl.o b/src/iccpd/src/mclagdctl/mclagdctl.o new file mode 100644 index 0000000000000000000000000000000000000000..0920a0d45ab142eae6ef20d6c1b7bbdc1eea302b GIT binary patch literal 86776 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 Uf9w. +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include "../include/mlacp_tlv.h" +#include "../include/mlacp_sync_prepare.h" +#include "../include/mlacp_link_handler.h" +#include "../include/mlacp_sync_update.h" + +#include + +/***************************************** +* Define +* +* ***************************************/ +#define MLACP_MSG_QUEUE_REINIT(list) \ + {\ + struct Msg* msg = NULL;\ + while (!TAILQ_EMPTY(&(list))) {\ + msg = TAILQ_FIRST(&(list));\ + TAILQ_REMOVE(&(list), msg, tail);\ + free(msg->buf);\ + free(msg);\ + }\ + TAILQ_INIT(&(list));\ + } + +#define PIF_QUEUE_REINIT(list) \ + { \ + while (!LIST_EMPTY(&(list))) { \ + struct PeerInterface* peer_if = NULL;\ + peer_if = LIST_FIRST(&(list)); \ + LIST_REMOVE(peer_if, mlacp_next); \ + free(peer_if); \ + } \ + LIST_INIT(&(list)); \ + } + +#define LIF_QUEUE_REINIT(list) \ + { \ + while (!LIST_EMPTY(&(list))) { \ + struct LocalInterface* lif = NULL;\ + lif = LIST_FIRST(&(list)); \ + if (lif->type == IF_T_PORT_CHANNEL && lif->is_arp_accept) { \ + if ((set_sys_arp_accept_flag(lif->name, 0)) == 0) \ + lif->is_arp_accept = 0; \ + } \ + LIST_REMOVE(lif, mlacp_next); \ + } \ + LIST_INIT(&(list)); \ + } + +#define LIF_PURGE_QUEUE_REINIT(list) \ + { \ + while (!LIST_EMPTY(&(list))) { \ + struct LocalInterface* lif = NULL;\ + lif = LIST_FIRST(&(list)); \ + LIST_REMOVE(lif, mlacp_purge_next); \ + } \ + LIST_INIT(&(list)); \ + } + +/***************************************** +* Static Function +* +* ***************************************/ +static char *mlacp_state(struct CSM* csm) ; +static void mlacp_resync_arp(struct CSM* csm); +static void mlacp_resync_mac(struct CSM* csm); +/* Sync Sender APIs*/ +static void mlacp_sync_send_sysConf(struct CSM* csm); +static void mlacp_sync_send_aggConf(struct CSM* csm); +static void mlacp_sync_send_aggState(struct CSM* csm); +static void mlacp_sync_send_syncArpInfo(struct CSM* csm); +static void mlacp_sync_send_heartbeat(struct CSM* csm); +static void mlacp_sync_send_syncDoneData(struct CSM* csm); +/* Sync Reciever APIs*/ +static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portConf(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portPrio(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portState(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_syncReq(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg); + +/* Sync Handler*/ +static void mlacp_sync_send_nak_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_sender_handler(struct CSM* csm); +static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_sync_send_all_info_handler(struct CSM* csm); + +/* Sync State Handler*/ +static void mlacp_stage_sync_send_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_stage_handler(struct CSM* csm, struct Msg* msg); +static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg); + +/****************************************************************** +* Sync Sender APIs +* +*****************************************************************/ +static void mlacp_sync_send_sysConf(struct CSM* csm) +{ + int msg_len = 0; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_sys_config(csm, g_csm_buf, CSM_BUFFER_SIZE); + if(msg_len > 0) + iccp_csm_send(csm, g_csm_buf, msg_len); + else + ICCPD_LOG_WARN("mlacp_fsm", " Invalid sysconf packet."); + + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] SysConf, len=[%d]", msg_len);*/ + + return; +} + +static void mlacp_sync_send_aggConf(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if, 0); + iccp_csm_send(csm, g_csm_buf, msg_len); + local_if->port_config_sync = 0; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ + } + } + + return; +} + +static void mlacp_sync_send_aggState(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + local_if->changed = 0; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ + } + } + + return; +} + +static void mlacp_sync_send_syncMacInfo(struct CSM* csm) +{ + int msg_len = 0; + struct Msg* msg = NULL; + + while (!TAILQ_EMPTY(&(MLACP(csm).mac_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).mac_msg_list), msg, tail); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct MACMsg*)msg->buf); + iccp_csm_send(csm, g_csm_buf, msg_len); + free(msg->buf); + free(msg); + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] MacInfo,len=[%d]", msg_len);*/ + } + + return; +} + +static void mlacp_sync_send_syncArpInfo(struct CSM* csm) +{ + int msg_len = 0; + struct Msg* msg = NULL; + + while (!TAILQ_EMPTY(&(MLACP(csm).arp_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_arp_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct ARPMsg*)msg->buf); + iccp_csm_send(csm, g_csm_buf, msg_len); + free(msg->buf); + free(msg); + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] ArpInfo,len=[%d]", msg_len);*/ + } + + return; +} + +static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_port_channel_info(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + local_if->changed = 0; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ + } + } + + return; +} + +static void mlacp_sync_send_syncPeerLinkInfo(struct CSM* csm) +{ + struct System* sys = NULL; + int msg_len = 0; + + if((sys = system_get_instance()) == NULL) + return; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + + return; +} + +static void mlacp_sync_send_heartbeat(struct CSM* csm) +{ + int msg_len = 0; + + if ((csm->heartbeat_send_time == 0) || + ((time(NULL) - csm->heartbeat_send_time) > 1)) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_heartbeat(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); + time(&csm->heartbeat_send_time); + } + + return; +} + +static void mlacp_sync_send_syncDoneData(struct CSM* csm) +{ + int msg_len = 0; + + /*Sync done & go to next stage*/ + MLACP(csm).wait_for_sync_data = 0; + memset(g_csm_buf, 0 , CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_sync_data_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE, 1); + iccp_csm_send(csm, g_csm_buf, msg_len); + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] SyncDone, len=[%d]", msg_len);*/ + + return; +} + +/****************************************************************** +* Sync Receiver APIs +* +*****************************************************************/ +static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg) +{ + mLACPSysConfigTLV* sysconf = NULL; + + sysconf = (mLACPSysConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); + + if(mlacp_fsm_update_system_conf(csm, sysconf)==-1) + { + /*NOTE: we just change the node ID local side without sending NAK msg*/ + ICCPD_LOG_DEBUG("mlacp_fsm", " Same Node ID = %d, send NAK",MLACP(csm).remote_system.node_id); + mlacp_sync_send_nak_handler(csm, msg); + } + + return; +} + +static void mlacp_sync_recv_portConf(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_portPrio(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_portState(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg) +{ + mLACPAggConfigTLV* portconf = NULL; + + portconf = (mLACPAggConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_Agg_conf(csm, portconf) == -1) + { + mlacp_sync_send_nak_handler(csm, msg); + } + + return; +} + +static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg) +{ + mLACPAggPortStateTLV* portstate = NULL; + + portstate = (mLACPAggPortStateTLV*) &(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_Aggport_state(csm, portstate) == -1) + { + mlacp_sync_send_nak_handler(csm, msg); + /*MLACP(csm).error_msg = "Receive a port state update on an non-existed port. It is suggest to check the environment and re-initialize mLACP again.";*/ + return; + } + + return; +} + +static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg) +{ + mLACPSyncDataTLV* syncdata = NULL; + + syncdata = (mLACPSyncDataTLV*)&(msg->buf[sizeof(ICCHdr)]); + if(syncdata->flags == 1) + { + /* Sync done*/ + MLACP(csm).wait_for_sync_data = 0; + } + + return; +} + +static void mlacp_sync_recv_syncReq(struct CSM* csm, struct Msg* msg) +{ + mLACPSyncReqTLV* mlacp_sync_req = NULL; + mlacp_sync_req = (mLACPSyncReqTLV*) &msg->buf[sizeof(ICCHdr)]; + MLACP(csm).sync_req_num = mlacp_sync_req->req_num; + + /* Reply the peer all sync info*/ + mlacp_sync_send_all_info_handler(csm); + + return; +} + +static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg) +{ + mLACPPortChannelInfoTLV* portconf = NULL; + + portconf = (mLACPPortChannelInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_port_channel_info(csm, portconf) == -1) + { + mlacp_sync_send_nak_handler(csm, msg); + } + + return; +} + +static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg) +{ + mLACPPeerLinkInfoTLV* peerlink = NULL; + + peerlink = (mLACPPeerLinkInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_peerlink_info( csm, peerlink); + + return; +} + +static void mlacp_sync_recv_macInfo(struct CSM* csm, struct Msg* msg) +{ + struct mLACPMACInfoTLV* mac_info = NULL; + + mac_info = (struct mLACPMACInfoTLV *) &(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_mac_info_from_peer(csm, mac_info); + + return; +} + +static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg) +{ + struct mLACPARPInfoTLV* arp_info = NULL; + + arp_info = (struct mLACPARPInfoTLV *) &(msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_arp_info(csm, arp_info); + + return; +} + +static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg) +{ + /*Don't support currently*/ + return; +} + +static void mlacp_sync_recv_heartbeat(struct CSM* csm, struct Msg* msg) +{ + struct mLACPHeartbeatTLV *tlv = NULL; + + tlv = (struct mLACPHeartbeatTLV *)(&msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_heartbeat(csm, tlv); + + return; +} + +/***************************************** +* MLACP Init +* +* ***************************************/ +void mlacp_init(struct CSM* csm, int all) +{ + if(csm == NULL) + return; + + MLACP(csm).sync_req_num = -1; + MLACP(csm).need_to_sync = 0; + MLACP(csm).error_msg = NULL; + + MLACP(csm).current_state = MLACP_STATE_INIT; + memset(MLACP(csm).remote_system.system_id, 0, ETHER_ADDR_LEN); + + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); + PIF_QUEUE_REINIT(MLACP(csm).pif_list); + LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list); + + if (all != 0) + { + /* if no clean all, keep the arp info & local interface info for next connection*/ + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list); + LIF_QUEUE_REINIT(MLACP(csm).lif_list); + + MLACP(csm).node_id = MLACP_SYSCONF_NODEID_MSB_MASK; + MLACP(csm).node_id |= (((inet_addr(csm->sender_ip) >> 24) << 4) & MLACP_SYSCONF_NODEID_NODEID_MASK); + MLACP(csm).node_id |= rand() % MLACP_SYSCONF_NODEID_FREE_MASK; + } + + return; +} + +/***************************************** +* MLACP finalize +* +* ***************************************/ +void mlacp_finalize(struct CSM* csm) +{ + if (csm == NULL) + return; + + /* msg destroy*/ + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list); + + /* remove lif & lif-purge queue */ + LIF_QUEUE_REINIT(MLACP(csm).lif_list); + LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list); + /* remove & destroy pif queue */ + PIF_QUEUE_REINIT(MLACP(csm).pif_list); + + return; +} + +/***************************************** +* MLACP FSM Transit +* +* ***************************************/ +void mlacp_fsm_transit(struct CSM* csm) +{ + struct System* sys = NULL; + struct Msg* msg = NULL; + static MLACP_APP_STATE_E prev_state = MLACP_SYNC_SYSCONF; + ICCHdr* icc_hdr = NULL; + ICCParameter* icc_param = NULL; + int have_msg=1; + + if (csm == NULL) + return; + if((sys = system_get_instance()) == NULL) + return; + + /* torn down event */ + if (csm->sock_fd <= 0 || csm->app_csm.current_state != APP_OPERATIONAL) + { + /* drop all legacy mlacp msg*/ + if (MLACP(csm).current_state != MLACP_STATE_INIT) + { + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); + MLACP(csm).current_state = MLACP_STATE_INIT; + } + return; + } + + /*Update port isolate after 3 seconds*/ + if(csm->isolate_update_time != 0 && (time(NULL) - csm->isolate_update_time) >= 3) + { + update_peerlink_isolate_from_all_csm_lif(csm); + csm->isolate_update_time = 0; + } + + mlacp_sync_send_heartbeat(csm); + + /* Dequeue msg if any*/ + while (have_msg) + { + if (MLACP(csm).current_state != MLACP_STATE_INIT) + { + /* Handler NAK First*/ + msg = mlacp_dequeue_msg(csm); + if (msg!=NULL) + { + have_msg=1; + icc_hdr = (ICCHdr*) msg->buf; + icc_param = (ICCParameter*) &msg->buf[sizeof(ICCHdr)]; + /*ICCPD_LOG_DEBUG("mlacp_fsm", " SYNC: Message Type = %X, TLV=%s, Len=%d", icc_hdr->ldp_hdr.msg_type, get_tlv_type_string(icc_param->type), msg->len);*/ + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION && icc_param->type == TLV_T_NAK) + { + mlacp_sync_recv_nak_handler(csm, msg); + free(msg->buf); + free(msg); + continue; + } + } + else + { + have_msg=0; + } + } + + if (prev_state != MLACP(csm).current_state) + { + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + mlacp_peerlink_conn_handler(csm); + prev_state = MLACP(csm).current_state; + } + + /* Sync State */ + if (MLACP(csm).current_state == MLACP_STATE_INIT) + { + MLACP(csm).wait_for_sync_data = 0; + MLACP(csm).current_state = MLACP_STATE_STAGE1; + mlacp_resync_mac(csm); + mlacp_resync_arp(csm); + } + + switch (MLACP(csm).current_state) + { + case MLACP_STATE_INIT: + case MLACP_STATE_ERROR: + /* should not be here*/ + break; + + case MLACP_STATE_STAGE1: + case MLACP_STATE_STAGE2: + mlacp_stage_handler(csm, msg); + break; + + case MLACP_STATE_EXCHANGE: + mlacp_exchange_handler(csm, msg); + break; + } + + /*ICCPD_LOG_DEBUG("mlacp_fsm", " Next State = %s", mlacp_state(csm));*/ + if (msg) + { + free(msg->buf); + free(msg); + } + } +} + +/* Helper function for dumping application state machine */ +static char* mlacp_state(struct CSM* csm) +{ + if (csm == NULL ) + return "MLACP_NULL"; + + switch (MLACP(csm).current_state) + { + case MLACP_STATE_INIT: + return "MLACP_STATE_INIT"; + case MLACP_STATE_STAGE1: + return "MLACP_STATE_STAGE1"; + case MLACP_STATE_STAGE2: + return "MLACP_STATE_STAGE2"; + case MLACP_STATE_EXCHANGE: + return "MLACP_STATE_EXCHANGE"; + case MLACP_STATE_ERROR: + return "MLACP_STATE_ERROR"; + } + + return "MLACP_UNKNOWN"; +} + +/* Add received message into message list */ +void mlacp_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + if (csm == NULL ) + { + if (msg != NULL ) + free(msg); + return; + } + + if (msg == NULL ) + return; + + #if 0 + icc_hdr = (ICCHdr*) msg->buf; + icc_param = (ICCParameter*) &msg->buf[sizeof(ICCHdr)]; + ICCPD_LOG_DEBUG("mlacp_fsm", " mLACP enqueue: tlv = 0x%04x", icc_param->type); + #endif + + TAILQ_INSERT_TAIL(&(MLACP(csm).mlacp_msg_list), msg, tail); + + return; +} + +/* Get received message from message list */ +struct Msg* mlacp_dequeue_msg(struct CSM* csm) +{ + struct Msg* msg = NULL; + + if (!TAILQ_EMPTY(&(MLACP(csm).mlacp_msg_list))) + { + msg = TAILQ_FIRST(&(MLACP(csm).mlacp_msg_list)); + TAILQ_REMOVE(&(MLACP(csm).mlacp_msg_list), msg, tail); + } + + return msg; +} + +/****************************************** +* When peerlink ready, prepare the MACMsg +* +******************************************/ +static void mlacp_resync_mac(struct CSM* csm) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + struct Msg *msg_send = NULL; + + /* recover MAC info sync from peer*/ + if(!TAILQ_EMPTY(&(MLACP(csm).mac_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*) msg->buf; + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } +} + +/****************************************** +* When peerlink ready, prepare the ARPMsg +* +******************************************/ +static void mlacp_resync_arp(struct CSM* csm) +{ + struct Msg* msg = NULL; + struct ARPMsg* arp_msg = NULL; + struct Msg *msg_send = NULL; + + /* recover ARP info sync from peer*/ + if(!TAILQ_EMPTY(&(MLACP(csm).arp_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + arp_msg->op_type = ARP_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + } + } + } +} + +/***************************************** +* NAK handler +* +* ***************************************/ +static void mlacp_sync_send_nak_handler(struct CSM* csm, struct Msg* msg) +{ + int msg_len; + ICCHdr* icc_hdr = NULL; + + icc_hdr = (ICCHdr*) msg->buf; + + ICCPD_LOG_WARN("mlacp_fsm", " ### Send NAK ###"); + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + csm->app_csm.invalid_msg_id = icc_hdr->ldp_hdr.msg_id; + msg_len = app_csm_prepare_nak_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); +} + +static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg) +{ + NAKTLV* naktlv = NULL; + uint16_t tlvType = -1; + int i; + + ICCPD_LOG_WARN("mlacp_fsm", " ### Receive NAK ###"); + + /* Dequeuq NAK*/ + naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; + + /* Check NAK Type*/ + for(i=0; irejected_msg_id == csm->msg_log.msg[i].msg_id) + { + tlvType = csm->msg_log.msg[i].tlv; + break; + } + } + + if(tlvType) + { + switch (tlvType) + { + case TLV_T_MLACP_SYSTEM_CONFIG: + MLACP(csm).node_id--; + MLACP(csm).system_config_changed=1; + ICCPD_LOG_WARN("mlacp_fsm", " [%X] change NodeID as %d", tlvType&0x00FF, MLACP(csm).node_id); + break; + + default: + ICCPD_LOG_WARN("mlacp_fsm", " [%X]", tlvType&0x00FF); + MLACP(csm).need_to_sync = 1; + break; + } + } + else + { + ICCPD_LOG_WARN("mlacp_fsm", " Unknow NAK"); + MLACP(csm).need_to_sync = 1; + } + + return; +} + +/***************************************** +* MLACP sync receiver +* +* ***************************************/ +static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg) +{ + ICCParameter *icc_param; + + /* No receive message...*/ + if (!csm || !msg) + return; + + icc_param = (ICCParameter*)&(msg->buf[sizeof(ICCHdr)]); + + /*fprintf(stderr, " Recv Type [%d]\n", icc_param->type);*/ + switch(icc_param->type) + { + case TLV_T_MLACP_SYSTEM_CONFIG: + mlacp_sync_recv_sysConf(csm, msg); + break; + + case TLV_T_MLACP_PORT_CONFIG: + mlacp_sync_recv_portConf(csm, msg); + break; + + case TLV_T_MLACP_PORT_PRIORITY: + mlacp_sync_recv_portPrio(csm, msg); + break; + + case TLV_T_MLACP_PORT_STATE: + mlacp_sync_recv_portState(csm, msg); + break; + + case TLV_T_MLACP_AGGREGATOR_CONFIG: + /* The following line will be uncommented when Aggregator related structures are supported. */ + mlacp_sync_recv_aggConf(csm, msg); + break; + + case TLV_T_MLACP_AGGREGATOR_STATE: + mlacp_sync_recv_aggState(csm, msg); + break; + + case TLV_T_MLACP_SYNC_DATA: + mlacp_sync_recv_syncData(csm, msg); + break; + + case TLV_T_MLACP_SYNC_REQUEST: + mlacp_sync_recv_syncReq(csm, msg); + break; + + case TLV_T_MLACP_PORT_CHANNEL_INFO: + mlacp_sync_recv_portChanInfo(csm, msg); + break; + + case TLV_T_MLACP_PEERLINK_INFO: + mlacp_sync_recv_peerLlinkInfo(csm, msg); + break; + + case TLV_T_MLACP_MAC_INFO: + mlacp_sync_recv_macInfo(csm, msg); + break; + + case TLV_T_MLACP_ARP_INFO: + mlacp_sync_recv_arpInfo(csm, msg); + break; + + case TLV_T_MLACP_STP_INFO: + mlacp_sync_recv_stpInfo(csm, msg); + break; + case TLV_T_MLACP_HEARTBEAT: + mlacp_sync_recv_heartbeat(csm, msg); + break; + } + + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [Sync Recv] %s... DONE", get_tlv_type_string(icc_param->type));*/ + + return; +} + +/***************************************** +* MLACP sync sender +* +* ***************************************/ +static void mlacp_sync_sender_handler(struct CSM* csm) +{ + switch(MLACP(csm).sync_state) + { + case MLACP_SYNC_SYSCONF: + mlacp_sync_send_sysConf(csm); + break; + + case MLACP_SYNC_AGGCONF: + /* Do nothing due to no support in this version. */ + mlacp_sync_send_aggConf(csm); + break; + + case MLACP_SYNC_AGGSTATE: + /* Do nothing due to no support in this version. */ + mlacp_sync_send_aggState(csm); + break; + + case MLACP_SYNC_AGGINFO: + mlacp_sync_send_syncPortChannelInfo(csm); + break; + + case MLACP_SYNC_PEERLINKINFO: + mlacp_sync_send_syncPeerLinkInfo(csm); + break; + + case MLACP_SYNC_ARP_INFO: + mlacp_sync_send_syncArpInfo(csm); + break; + + case MLACP_SYNC_DONE: + mlacp_sync_send_syncDoneData(csm); + break; + + default: + break; + }; + + return; +} + +static void mlacp_sync_send_all_info_handler(struct CSM* csm) +{ + size_t len = 0; + + /* Prepare for sync start reply*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_sync_data_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE, 0); + iccp_csm_send(csm, g_csm_buf, len); + + MLACP(csm).sync_state = MLACP_SYNC_SYSCONF; + while(1) + { + mlacp_sync_sender_handler(csm); + if(MLACP(csm).sync_state != MLACP_SYNC_DONE) + { + MLACP(csm).sync_state++; + } + else + { + /*Next stage*/ + MLACP(csm).wait_for_sync_data = 0; + MLACP(csm).current_state++; + break; + } + } + + return; +} + +static void mlacp_stage_sync_send_handler(struct CSM* csm, struct Msg* msg) +{ + ICCHdr* icc_hdr = NULL; + ICCParameter* icc_param = NULL; + mLACPSyncReqTLV* mlacp_sync_req = NULL; + + if (MLACP(csm).wait_for_sync_data == 0) + { + /* Waiting the peer sync request*/ + if(msg){ + icc_hdr = (ICCHdr*) msg->buf; + icc_param = (ICCParameter*) &msg->buf[sizeof(ICCHdr)]; + + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA && icc_param->type == TLV_T_MLACP_SYNC_REQUEST) + { + mlacp_sync_req = (mLACPSyncReqTLV*) &msg->buf[sizeof(ICCHdr)]; + MLACP(csm).wait_for_sync_data = 1; + MLACP(csm).sync_req_num = mlacp_sync_req->req_num; + + /* Reply the peer all sync info*/ + mlacp_sync_send_all_info_handler(csm); + } + } + } + + return; +} + +static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg) +{ + int msg_len=0; + /* Socket server send sync request first*/ + if (MLACP(csm).wait_for_sync_data == 0) + { + // Send out the request for ALL + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_sync_request_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); + MLACP(csm).wait_for_sync_data = 1; + } + else + { + mlacp_sync_receiver_handler(csm, msg); + if(MLACP(csm).wait_for_sync_data == 0) + { + MLACP(csm).current_state++; + } + } + + return; +} + +static void mlacp_stage_handler(struct CSM* csm, struct Msg* msg) +{ + if(MLACP(csm).current_state==MLACP_STATE_STAGE1) + { + /*Stage 1, role active send info first*/ + if (csm->role_type == STP_ROLE_ACTIVE) + mlacp_stage_sync_send_handler(csm, msg); + else + mlacp_stage_sync_request_handler(csm, msg); + } + else + { + /*Stage 2, role standby send info*/ + if (csm->role_type == STP_ROLE_ACTIVE) + mlacp_stage_sync_request_handler(csm, msg); + else + mlacp_stage_sync_send_handler(csm, msg); + } + + return; +} + +static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) +{ + int len; + struct System* sys = NULL; + struct LocalInterface* lif = NULL, *lif_purge = NULL; + + ICCHdr* icc_hdr = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + /* update system id*/ + update_system_id(csm); + + /* Any msg?*/ + if (msg) + { + icc_hdr = (ICCHdr*) msg->buf; + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + { + /* Process receive APP info*/ + mlacp_sync_receiver_handler(csm, msg); + } + } + + if (MLACP(csm).need_to_sync != 0) + { + /* Send out the request for ALL info*/ + MLACP(csm).need_to_sync = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_sync_request_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + } + + /* Send system config*/ + if (MLACP(csm).system_config_changed != 0) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_sys_config(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, len); + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); + iccp_csm_send(csm, g_csm_buf, len); + + MLACP(csm).system_config_changed = 0; + } + + /* Send mlag purge lif*/ + LIST_FOREACH(lif_purge, &(MLACP(csm).lif_purge_list), mlacp_purge_next) + { + /* Purge info*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif_purge,1); + iccp_csm_send(csm, g_csm_buf, len); + /* Destroy old interface*/ + if (lif_purge != NULL) + LIST_REMOVE(lif_purge, mlacp_purge_next); + } + + /* Send mlag lif*/ + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type == IF_T_PORT_CHANNEL && lif->port_config_sync) + { + /* Send port channel information*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif,0); + iccp_csm_send(csm, g_csm_buf, len); + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_port_channel_info(csm, g_csm_buf, CSM_BUFFER_SIZE, lif); + iccp_csm_send(csm, g_csm_buf, len); + + lif->port_config_sync = 0; + } + + /*send if portchannel state change */ + if (lif->type == IF_T_PORT_CHANNEL && lif->changed) + { + /* Send port channel state information*/ + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, lif); + iccp_csm_send(csm, g_csm_buf, len); + lif->changed = 0; + } + } + + /* Send MAC info if any*/ + mlacp_sync_send_syncMacInfo(csm); + + /* Send ARP info if any*/ + mlacp_sync_send_syncArpInfo(csm); + + return; +} \ No newline at end of file diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c new file mode 100644 index 000000000000..e18743b18a0d --- /dev/null +++ b/src/iccpd/src/mlacp_link_handler.c @@ -0,0 +1,1789 @@ +/* +* mlacp_link_handler.c +* mLACP link handler +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_tlv.h" + +#include "../include/mlacp_link_handler.h" + +#include "mclagdctl/mclagdctl.h" + +/***************************************** +* Enum +* +* ***************************************/ +typedef enum route_manipulate_type { + ROUTE_NONE, + ROUTE_ADD, + ROUTE_DEL +} ROUTE_MANIPULATE_TYPE_E; + + +/***************************************** +* Global +* +* ***************************************/ +char g_ipv4_str[INET_ADDRSTRLEN]; + +static int arp_set_handler(struct CSM* csm, + struct LocalInterface* lif, + int add) +{ + struct Msg* msg = NULL; + struct ARPMsg* arp_msg = NULL; + char mac_str[18] = ""; + + if (!csm || !lif) + return 0; + + if (add) + goto add_arp; + else + goto del_arp; + + /* Process Add */ +add_arp: + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return 0; + + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + mac_str[0] = '\0'; + arp_msg = (struct ARPMsg*) msg->buf; + + /* only process add*/ + if (arp_msg->op_type == ARP_SYNC_DEL) + continue; + + /* find the ARP for lif_list*/ + if (strcmp(lif->name, arp_msg->ifname) != 0) + continue; + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], + arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); + + mlacp_fsm_arp_set(arp_msg->ifname, arp_msg->ipv4_addr, mac_str); + ICCPD_LOG_DEBUG(__FUNCTION__, "Add dynamic ARP to kernel [%s]", + show_ip_str(arp_msg->ipv4_addr)); + } + goto done; + +del_arp: + /* Process Del */ + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + + /* find the ARP for lif_list*/ + if (strcmp(lif->name, arp_msg->ifname) != 0) + continue; + + /* don't process del*/ + if (arp_msg->op_type == ARP_SYNC_DEL) + continue; + + mlacp_fsm_arp_del(arp_msg->ifname, arp_msg->ipv4_addr); + /* link broken, del all static arp on the lif*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Del dynamic ARP [%s]", + show_ip_str(arp_msg->ipv4_addr)); + } + +done: + return 0; +} + +/***************************************** +* Port-Channel Status Handler +* +****************************************/ +static void set_route_by_linux_route(struct CSM* csm, + struct LocalInterface *local_if, + int is_add) +{ + /* TODO Need to remove this function + when set static route with zebra works fine*/ + + char ipv4_dest_str[INET_ADDRSTRLEN]; + char syscmd[128]; + char *ptr; + int ret = 0; + + /* enable kernel forwarding support*/ + system("echo 1 > /proc/sys/net/ipv4/ip_forward"); + + if(!csm || !local_if) + return; + + sprintf(ipv4_dest_str, "%s", show_ip_str(htonl(local_if->ipv4_addr))); + ptr=strrchr(ipv4_dest_str, '.');strcpy(ptr, ".0\0"); + +#if 1 + /* set gw route*/ + /*sprintf(syscmd, "ip route %s %s/%d proto static metric 200 nexthop via %s > /dev/null 2>&1",*/ + sprintf(syscmd, "ip route %s %s/%d metric 200 nexthop via %s > /dev/null 2>&1", + (is_add)?"add":"del", ipv4_dest_str, local_if->prefixlen, + csm->peer_ip); +#else + // set interface route + sprintf(syscmd, "route %s -net %s/%d %s > /dev/null 2>&1", + (is_add)?"add":"del", ipv4_dest_str, local_if->prefixlen, + local_if->name); +#endif + + ret = system(syscmd); + ICCPD_LOG_DEBUG(__FUNCTION__, " %s ret = %d", syscmd,ret); + + return; +} + +static void update_vlan_if_info(struct CSM *csm, + struct LocalInterface *local_if, + struct LocalInterface *vlan_if, + int po_state) +{ + if (!csm || !local_if || !vlan_if) + return; + + vlan_if->mlacp_state = MLACP(csm).current_state; + + return; +} + +static void update_l3_if_info(struct CSM *csm, + struct LocalInterface *local_if, + struct LocalInterface *l3_if, + int po_state) +{ + if (!csm || !l3_if) + return; + + l3_if->mlacp_state = MLACP(csm).current_state; + + return; +} + +static void update_po_if_info(struct CSM *csm, + struct LocalInterface *local_if, + int po_state) +{ + if (!csm || !local_if) + return; + + /* update local po info*/ + if(local_if->po_active != po_state) + { + local_if->changed = 1; + local_if->po_active = (po_state!=0); + /*printf("update po [%s=%d]\n",local_if->name, local_if->po_active);*/ + } + local_if->mlacp_state = MLACP(csm).current_state; + + return; +} + +static void set_l3_itf_state(struct CSM *csm, + struct LocalInterface *set_l3_local_if, + ROUTE_MANIPULATE_TYPE_E route_type) +{ + if (!csm || !set_l3_local_if) + return; + + if (set_l3_local_if && (route_type != ROUTE_NONE)) + { + /*set_default_route(csm);*/ + + ICCPD_LOG_DEBUG(__FUNCTION__, " route set Interface = %s route type = %d route = %s nexthop via = %s ", + set_l3_local_if->name, route_type, show_ip_str(set_l3_local_if->ipv4_addr), csm->peer_ip ); + + /* set static route*/ + if(route_type == ROUTE_ADD) + { + /*set_route_by_linux_route(csm, set_l3_local_if, 1);*/ /*add static route by linux route tool*/ + arp_set_handler(csm, set_l3_local_if, 0); /* del arp*/ + } + else if(route_type == ROUTE_DEL) + { + /*set_route_by_linux_route(csm, set_l3_local_if, 0);*/ /*del static route by linux route tool*/ + arp_set_handler(csm, set_l3_local_if, 1); /* add arp*/ + } + } + + return; +} + +static int peer_po_is_alive(struct CSM *csm, int po_ifindex) +{ + struct PeerInterface *pif = NULL; + int pif_active = 0; + + if (!csm) + return 0; + + LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) + { + if(pif->type != IF_T_PORT_CHANNEL) + continue; + if(pif->po_id!= po_ifindex) + continue; + + if(pif->po_active) + pif_active = 1; /*pif alive*/ + break; + } + + return pif_active; +} + +static void mlacp_clean_fdb (void) +{ + struct IccpSyncdHDr * msg_hdr; + char msg_buf[4096] = {0}; + int msg_len; + + struct System *sys; + + sys = system_get_instance(); + if(sys == NULL) + return; + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_FLUSH_FDB; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + if(sys->sync_fd) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + ICCPD_LOG_DEBUG(__FUNCTION__, "notify mclagsyncd clear fdb"); + + return; +} + +void set_peerlink_mlag_port_learn (struct LocalInterface *lif, int enable) +{ + struct IccpSyncdHDr * msg_hdr; + mclag_sub_option_hdr_t * sub_msg; + char msg_buf[4096]; + int msg_len; + struct System *sys; + + sys = system_get_instance(); + if(sys == NULL) + return; + + if (!lif) + return; + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE; + + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + sub_msg =(mclag_sub_option_hdr_t*) &msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE; + + if(enable) + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE; + + msg_len = strlen(lif->name); + memcpy(sub_msg->data, lif->name, msg_len); + + sub_msg->op_len = msg_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + ICCPD_LOG_DEBUG(__FUNCTION__, " send port-learn msg to sync for %s , member %s", + lif->name, sub_msg->data); + + /*send msg*/ + if(sys->sync_fd) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + +static void set_peerlink_mlag_port_kernel_forward ( + struct CSM *csm, + struct LocalInterface *lif, + int enable) +{ + struct VLAN_ID* vlan_id = NULL; + + if (!csm || !csm->peer_link_if || !lif) + return; + + char cmd[256] = {0}; + + sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP", + "-D", csm->peer_link_if->name, lif->name); + ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s",cmd ); + system(cmd); + + sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP", + (enable)?"-A":"-D", csm->peer_link_if->name, lif->name); + ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s",cmd ); + system(cmd); + + return; +} + +void update_peerlink_isolate_from_all_csm_lif ( + struct CSM* csm) +{ + struct LocalInterface *lif = NULL; + struct IccpSyncdHDr * msg_hdr; + mclag_sub_option_hdr_t * sub_msg; + char msg_buf[4096]; + struct System *sys; + + char mlag_po_buf[512]; + int src_len = 0,dst_len =0; + char src_buf[2048]; + + sys = system_get_instance(); + if(sys == NULL) + return; + + if (!csm || !csm->peer_link_if) return; + + memset(msg_buf,0,4095); + memset(mlag_po_buf,0, 511); + memset(src_buf,0,2047); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_PORT_ISOLATE; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + /*sub msg src*/ + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC; + + if(csm->peer_link_if->type == IF_T_PORT) + { + src_len= strlen(csm->peer_link_if->name); + memcpy(sub_msg->data, csm->peer_link_if->name, src_len); + } + else + { + src_len= strlen(csm->peer_link_if->portchannel_member_buf); + memcpy(sub_msg->data, csm->peer_link_if->portchannel_member_buf, src_len); + } + sub_msg->op_len = src_len; + + /*sub msg dst */ + msg_hdr->len += sub_msg->op_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_ISOLATE_DST; + + /*traverse all portchannel member port and send msg to syncd */ + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if(lif->type !=IF_T_PORT_CHANNEL) + continue; + + /* check pif port state and lif pochannel state */ + if(lif->isolate_to_peer_link == 1) + { + /* need to isolate port, get it's member name */ + if(strlen(mlag_po_buf) != 0) + dst_len += snprintf(mlag_po_buf+dst_len, sizeof(mlag_po_buf)-dst_len, "%s",","); + + dst_len += snprintf(mlag_po_buf+dst_len, sizeof(mlag_po_buf)-dst_len, "%s", lif->portchannel_member_buf); + } + } + + sub_msg->op_len = dst_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + if(dst_len) + { + memcpy(sub_msg->data, mlag_po_buf, dst_len); + ICCPD_LOG_DEBUG(__FUNCTION__, "isolate dst %s, data %s, len %d",mlag_po_buf, sub_msg->data, dst_len); + } + + /*send msg*/ + if(sys->sync_fd) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + +static void set_peerlink_mlag_port_isolate ( + struct CSM *csm, + struct LocalInterface *lif, + int enable) +{ + if (!csm || !csm->peer_link_if || !lif) + return; + + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + lif->isolate_to_peer_link = enable; + + /*update_peerlink_isolate_from_all_csm_lif(csm);*/ + csm->isolate_update_time = time(NULL); + + /* Kernel also needs to block traffic from peerlink to mlag-port*/ + set_peerlink_mlag_port_kernel_forward(csm, lif, enable); + + return; +} + +void peerlink_port_isolate_cleanup(struct CSM* csm) +{ + struct LocalInterface *local_if=NULL; + struct VLAN_ID *vlan=NULL; + + if (!csm) + return; + + /* Clean all port block*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if(local_if->type == IF_T_PORT_CHANNEL) + { + set_peerlink_mlag_port_isolate(csm, local_if, 0); + } + } + + return; +} + +void update_peerlink_isolate_from_pif ( + struct CSM *csm, + struct PeerInterface *pif, + int pif_po_state, + int new_create) +{ + struct LocalInterface *lif = NULL; + int lif_po_state = 1; + + if(!csm || !csm->peer_link_if || !pif) return; + if(new_create == 0 && pif_po_state == pif->po_active) return; + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + /* peer link changed*/ + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if(strcmp(lif->name, pif->name)!=0) + continue; + + lif_po_state = lif->po_active; + break; + } + + if (!lif) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "can't find lif"); + return; + } + + ICCPD_LOG_DEBUG(__FUNCTION__, " from peer %s local(%s) / peer(%s)", + lif->name, + (lif_po_state) ? "up" : "down", + (pif_po_state) ? "up" : "down"); + + if (lif_po_state == 1) + { + if (pif_po_state == 1) + { + /* both peer-pair link up, enable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, " Enable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 1); + } + else + { + /* local link up, and peer link changes to down, disable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Disable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 0); + } + } + else + { + ;/* local link down, do nothing*/ + } + + return; +} + +static void update_peerlink_isolate_from_lif ( + struct CSM* csm, + struct LocalInterface* lif, + int lif_po_state) +{ + struct PeerInterface *pif = NULL; + int pif_po_state = 1; + + if (!csm || !csm->peer_link_if || !lif) return; + /*if (lif_po_state == lif->po_active) return;*/ + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + /* local link changed*/ + LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) + { + if (strcmp(pif->name, lif->name)!=0) + continue; + + pif_po_state = pif->po_active; + break; + } + + ICCPD_LOG_DEBUG(__FUNCTION__, " from local %s local(%s) / peer(%s)", + lif->name,(lif_po_state) ? "up" : "down", (pif_po_state) ? "up" : "down"); + + if (lif_po_state == 1) + { + if (pif_po_state == 1) + { + /* both peer-pair link up, enable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Enable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 1); + } + else + { + /* peer link down, local link changes to up, disable port-isolate*/ + ICCPD_LOG_DEBUG(__FUNCTION__, " Disable port-isolate from %s to %s", + csm->peer_link_if->name, lif->name); + set_peerlink_mlag_port_isolate(csm, lif, 0); + } + } + else + { + ;/* local link down, do nothing*/ + } + + return; +} + +static void update_l2_po_state(struct CSM *csm, + struct LocalInterface *lif, + int po_state) +{ + ROUTE_MANIPULATE_TYPE_E route_type=ROUTE_NONE; + struct VLAN_ID *vlan=NULL; + struct LocalInterface *set_l3_vlan_if=NULL; + + if (!csm || !lif) + return; + + /*L2 po*/ + /*if (po_state != lif->po_active && po_state == 0) + { + mlacp_clean_fdb(); + }*/ + + /*Is there any L3 vlan over L2 po?*/ + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + route_type = ROUTE_NONE; + + if(!vlan->vlan_itf) + continue; + + /* If the po is under a vlan, update vlan state first*/ + update_vlan_if_info(csm, lif, vlan->vlan_itf, po_state); + + if(!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + /*NOTE + * assume only one mlag per vlan + * need to add rules for per mlag per vlan later (arp list?) + */ + set_l3_vlan_if = vlan->vlan_itf; + if (po_state != lif->po_active + || MLACP(csm).current_state != set_l3_vlan_if->mlacp_state) + { + if(po_state==1) + { + route_type = ROUTE_DEL; + } + else if(po_state == 0 + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + if (peer_po_is_alive(csm, lif->ifindex) == 1) + route_type = ROUTE_ADD; + } + } + + /*update_po_arp_list(csm, set_l3_vlan_if);*/ + set_l3_itf_state(csm, set_l3_vlan_if, route_type); + update_l3_if_info(csm, lif, set_l3_vlan_if, po_state); + } + + return; +} + +static void update_l3_po_state(struct CSM *csm, + struct LocalInterface *lif, + int po_state) +{ + ROUTE_MANIPULATE_TYPE_E route_type=ROUTE_NONE; + struct LocalInterface *set_l3_lif=NULL; + /*L3 po*/ + set_l3_lif = lif; + + if (!csm || !lif) + return; + + if(po_state != lif->po_active + && po_state == 1) + { + /* po alive, clean static route & recover the ARP*/ + route_type = ROUTE_DEL; + } + else if(po_state != lif->po_active + && po_state == 0 + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /* po is not alive & peer-link alive, set static route*/ + if (peer_po_is_alive(csm, lif->po_id) == 1) + route_type = ROUTE_ADD; + } + else if(MLACP(csm).current_state != lif->mlacp_state + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE + && po_state == 0) + { + /* when peer-pair link ready, set static route for broken po link*/ + if (peer_po_is_alive(csm, lif->po_id) == 1) + route_type = ROUTE_ADD; + } + + /*update_po_arp_list(csm, set_l3_lif);*/ + set_l3_itf_state(csm, set_l3_lif, route_type); + update_l3_if_info(csm, lif, set_l3_lif, po_state); + + return; +} + +int is_local_vlan_on(struct VLAN_ID* vlan_id_list) +{ + if(!vlan_id_list->vlan_itf) + return 0; + + return 1; +} + +void syn_arp_info_to_peer(struct CSM *csm, struct LocalInterface *local_if) +{ + struct Msg *msg = NULL; + struct ARPMsg *arp_msg = NULL, *arp_info = NULL; + struct Msg *msg_send = NULL; + + if(!csm || !local_if) + return; + + if(!TAILQ_EMPTY(&(MLACP(csm).arp_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) + { + arp_info = (struct ARPMsg*) msg->buf; + + if(strcmp(arp_info->ifname, local_if->name)!=0) + continue; + + arp_msg = (struct ARPMsg*) msg->buf; + arp_msg->op_type = ARP_SYNC_ADD; + + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG( __FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + else + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + show_ip_str(arp_msg->ipv4_addr)); + } + } + + return; +} + +void update_stp_peer_link(struct CSM *csm, + struct PeerInterface *pif, + int po_state, int new_create) +{ + struct LocalInterface *lif=NULL; + struct VLAN_ID *vlan=NULL; + + if(!csm || !pif) + return; + if(new_create == 0 && po_state == pif->po_active) + return; + + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if(strcmp(lif->name, pif->name)!=0) + continue; + + /* update lif route if pif link status changes */ + if (local_if_is_l3_mode(lif)) + { + if (po_state == 1 && lif->po_active == 0) + set_l3_itf_state(csm, lif, ROUTE_ADD); + else if (po_state == 0 && lif->po_active == 0) + set_l3_itf_state(csm, lif, ROUTE_DEL); + + /*If pif change to active, and local is also active, syn arp to peer*/ + if (po_state == 1 && lif->po_active == 1) + { + syn_arp_info_to_peer(csm, lif); + } + } + else + { + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if(!is_local_vlan_on(vlan)) + continue; + if(!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + /*NOTE + * assume only one mlag per bridge + * need to add rules for per mlag per bridge later (arp list?) + */ + if (po_state == 1 && lif->po_active == 0) + set_l3_itf_state(csm, vlan->vlan_itf, ROUTE_ADD); + else if (po_state == 0 && lif->po_active == 0) + set_l3_itf_state(csm, vlan->vlan_itf, ROUTE_DEL); + + /*If pif change to active, and local is also active, syn arp to peer*/ + if (po_state == 1 && lif->po_active == 1) + { + syn_arp_info_to_peer(csm, vlan->vlan_itf); + } + } + } + + break; + } + + return; +} + +void iccp_get_fdb_change_from_syncd( void) +{ + struct IccpSyncdHDr * msg_hdr; + char msg_buf[4096]; + struct System *sys; + + sys = system_get_instance(); + if(sys == NULL) + return; + + memset(msg_buf,0,4095); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_GET_FDB_CHANGES; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d write get fdb change msg ", + sys->sync_fd); + + /*send msg*/ + if(sys->sync_fd > 0) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + +void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg,uint8_t mac_type) +{ + struct IccpSyncdHDr * msg_hdr; + char msg_buf[4096]; + struct System *sys; + struct mclag_fdb_info * mac_info; + + sys = system_get_instance(); + if(sys == NULL) + return; + + memset(msg_buf,0,4095); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_SET_FDB; + + /*mac msg */ + mac_info = (struct mclag_fdb_info *)&msg_buf[sizeof(struct IccpSyncdHDr)]; + mac_info->vid = mac_msg->vid; + memcpy(mac_info->port_name,mac_msg->ifname,MAX_L_PORT_NAME); + memcpy(mac_info->mac ,mac_msg->mac_str,32); + mac_info->type = mac_type; + mac_info->op_type = mac_msg->op_type; + msg_hdr->len = sizeof(struct IccpSyncdHDr)+sizeof(struct mclag_fdb_info); + + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d write mac msg vid : %d ; ifname %s ; mac %s fdb type %d ; op type %d ", + sys->sync_fd,mac_info->vid,mac_info->port_name,mac_info->mac, mac_info->type,mac_info->op_type); + + /*send msg*/ + if(sys->sync_fd > 0 ) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + +void add_mac_to_chip(struct MACMsg* mac_msg, uint8_t mac_type) +{ + mac_msg->op_type = MAC_SYNC_ADD; + iccp_send_fdb_entry_to_syncd( mac_msg, mac_type); + + return; +} + +void del_mac_from_chip(struct MACMsg* mac_msg) +{ + mac_msg->op_type = MAC_SYNC_DEL; + iccp_send_fdb_entry_to_syncd( mac_msg, mac_msg->fdb_type); + + return; +} + +uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t set ) +{ + uint8_t new_age_flag = 0; + struct Msg *msg = NULL; + + new_age_flag = mac_msg->age_flag; + + if(set == 0)/*remove age flag*/ + { + if(new_age_flag & MAC_AGE_LOCAL) + { + new_age_flag &= ~MAC_AGE_LOCAL; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove local age flag: %d ifname %s, add %s vlan-id %d, age_flag %d", + new_age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + + /*send mac MAC_SYNC_ADD message to peer*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } + } + else/*set age flag*/ + { + if(!(new_age_flag & MAC_AGE_LOCAL)) + { + new_age_flag |= MAC_AGE_LOCAL; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Add local age flag: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + + /*send mac MAC_SYNC_DEL message to peer*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + mac_msg->op_type = MAC_SYNC_DEL; + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } + } + + return new_age_flag; +} + +/*Deal with mac add,del,move when portchannel up or down*/ +static void update_l2_mac_state(struct CSM *csm, + struct LocalInterface *lif, + int po_state) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + + if (!csm || !lif) + return; + + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*) msg->buf; + + /* find the MAC for this interface*/ + if (strcmp(lif->name, mac_msg->origin_ifname) != 0) + continue; + + /*portchannel down*/ + if(po_state == 0) + { + #if 1 + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down,flag %d del MAC: %s, MAC %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + if(mac_msg->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + { + /*send mac del message to mclagsyncd.*/ + if(mac_msg->fdb_type != MAC_TYPE_STATIC) + del_mac_from_chip(mac_msg); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, del MAC: %s, MAC %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + /*If local and peer both aged, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, flag %d redirect MAC to peer-link: %s, MAC %s vlan-id %d", + mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + /*First del the old item*/ + /*del_mac_from_chip(mac_msg);*/ + + /*If local is aged but peer is not aged, redirect the mac to peer-link*/ + memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + + /*sleep 10ms, avoid orchagent mix the del event*/ + /*usleep(100000);*/ + + /*Send mac add message to mclagsyncd. fdb_type is not changed*/ + /*Is need to delete the old item before add?(Old item probably is static)*/ + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + #endif + } + else /*portchannel up*/ + { + if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf up, redirect MAC to portchannel: %s, MAC %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + /*Remove MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm,mac_msg, 0); + + /*Send mac del message to mclagsyncd, current port is peer-link*/ + /*del_mac_from_chip(mac_msg);*/ + + /*Reverse interface from peer-link to the original portchannel*/ + memcpy(mac_msg->ifname, mac_msg->origin_ifname, MAX_L_PORT_NAME); + + /*sleep 10ms, avoid orchagent mix the del event*/ + /*sleep(100000);*/ + + /*Send dynamic or static mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, mac_msg->fdb_type); + } + } + } + + return; +} + +void mlacp_portchannel_state_handler(struct CSM* csm, + struct LocalInterface* local_if, + int po_state) +{ + if (!csm || !local_if) + return; + + update_peerlink_isolate_from_lif(csm, local_if, po_state); + + update_l2_mac_state(csm, local_if, po_state); + + if(!local_if_is_l3_mode(local_if)) + update_l2_po_state(csm, local_if, po_state); + else + update_l3_po_state(csm, local_if, po_state); + + update_po_if_info(csm, local_if, po_state); + + return; +} + +static void mlacp_conn_handler_fdb (struct CSM* csm) +{ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + struct Msg *msg_send = NULL; + + if (!csm) + return; + + if(!TAILQ_EMPTY(&(MLACP(csm).mac_list))) + { + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*) msg->buf; + + /*Wait the ACK from peer?*/ + /*mac_msg->age_flag &= ~MAC_AGE_PEER;*/ + + /*Send mac add message to peer*/ + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + } + + return; +} + +/***************************************** +* Peer-Link connect/disconnect handler +* +* ***************************************/ +void mlacp_peerlink_conn_handler(struct CSM* csm) +{ + struct LocalInterface *lif = NULL; + struct PeerInterface *pif = NULL; + struct VLAN_ID *vlan = NULL; + static int first_time = 0; + + if (!csm) + return; + + set_peerlink_mlag_port_learn(csm->peer_link_if, 0); + + if(first_time == 0) + { + first_time = 1; + mlacp_clean_fdb(); + } + + iccp_get_fdb_change_from_syncd(); + + mlacp_conn_handler_fdb(csm); + +#if 0 + // When peer-link ready, suppose all MLAG link are alive + LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) + { + pif->po_active = 1; + } +#endif + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if(lif->type == IF_T_PORT_CHANNEL) + { + if(local_if_is_l3_mode(lif)) + { + set_route_by_linux_route( csm, lif, 1); + } + else + { + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if(!vlan->vlan_itf) + continue; + if(!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + set_route_by_linux_route(csm, vlan->vlan_itf, 1); /* add static route by linux route tool*/ + } + } + + mlacp_portchannel_state_handler(csm, lif,(lif->state==PORT_STATE_UP)?1:0); + } + } + + return; +} + +void mlacp_peerlink_disconn_handler(struct CSM* csm) +{ +/*If peer disconnect, remove all the mac that point to the peer-link, +do not clean static route,arp,port block, ARP will ageout, port block +will recalculate after peer connected.*/ + struct Msg* msg = NULL; + struct MACMsg* mac_msg = NULL; + + if (!csm) + return; + + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) + { + mac_msg = (struct MACMsg*) msg->buf; + + mac_msg->age_flag |= MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + + /* find the MAC that the port is peer-link*/ + if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer disconnect, del MAC for peer-link: %s, MAC %s vlan-id %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + /*Send mac del message to mclagsyncd*/ + del_mac_from_chip(mac_msg); + + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + +#if 0 + struct LocalInterface *local_if=NULL; + struct VLAN_ID *vlan=NULL; + + if (!csm) + return; + + /*set_peerlink_mlag_port_learn(csm, 1);*/ + + /* Clean all L3 static route & arp info*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if(local_if->type == IF_T_PORT_CHANNEL) { + set_peerlink_mlag_port_isolate(csm, local_if, 0); + + if(local_if_is_l3_mode(local_if)){ + /*set_route_by_linux_route(csm, local_if, 0);*/ /* del static route by linux route tool*/ + arp_set_handler(csm, local_if, 0); /* del arp*/ + } + else { + LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) + { + if(!vlan->vlan_itf) + continue; + if(!local_if_is_l3_mode(vlan->vlan_itf)) + continue; + + /*set_route_by_linux_route(csm, vlan->vlan_itf, 0);*/ /*del static route by linux route tool*/ + arp_set_handler(csm, vlan->vlan_itf, 0); /* del arp*/ + } + } + } + } +#endif + + return; +} + +/***************************************** +* Po add/remove handler +* +*****************************************/ +void mlacp_mlag_link_add_handler(struct CSM *csm, struct LocalInterface *lif) +{ + if (!csm || !lif) + return; + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + set_peerlink_mlag_port_isolate(csm, lif, 1); + + return; +} + +void mlacp_mlag_link_del_handler(struct CSM *csm, struct LocalInterface *lif) +{ + if (!csm || !lif) + return; + + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; + + set_peerlink_mlag_port_isolate(csm, lif, 0); + + return; +} + +/***************************************** +* Tool : show ip string +* +* ***************************************/ +char *show_ip_str(uint32_t ipv4_addr) +{ + struct in_addr in_addr; + + memset(g_ipv4_str, 0 ,sizeof(g_ipv4_str)); + in_addr.s_addr = ipv4_addr; + inet_ntop(AF_INET, &in_addr, g_ipv4_str, INET_ADDRSTRLEN); + + return g_ipv4_str; +} + +int iccp_connect_syncd() +{ + struct System* sys = NULL; + int ret = 0; + int fd = 0; + struct sockaddr_in serv; + static int count = 0; + + if ((sys = system_get_instance()) == NULL) + goto conn_fail; + + if(sys->sync_fd >= 0) + return 0; + + /*Print the fail log message every 60s*/ + if(count >= 600) + { + count = 0; + } + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + { + if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to create unix socket: %s", strerror(errno)); + goto conn_fail; + } + + /* Make server socket. */ + memset(&serv, 0, sizeof(serv)); + serv.sin_family = AF_INET; + serv.sin_port = htons(2626); +#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN + serv.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ + serv.sin_addr.s_addr = htonl(0x7f000006); + + ret = connect(fd, (struct sockaddr *)&serv, sizeof(serv)); + if (ret < 0) { + if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to connect to mclag syncd: errno str %s", strerror(errno)); + close(fd); + goto conn_fail; + } + + ICCPD_LOG_WARN(__FUNCTION__, "success to link syncd"); + sys->sync_fd = fd; + + struct epoll_event event; + int err; + event.data.fd = fd; + event.events = EPOLLIN; + ret = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, fd, &event); + + count = 0; + return 0; + +conn_fail: + if(count == 0) ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclag syncd socket connect fail", + __FUNCTION__, __LINE__); + + count++; + + return -1; +} + +void syncd_info_close() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + if(sys->sync_fd > 0) + { + close(sys->sync_fd); + sys->sync_fd = -1; + } + + return; +} + + int iccp_get_receive_fdb_sock_fd(struct System *sys) +{ + return sys->sync_fd; +} + + int iccp_receive_fdb_handler_from_syncd(struct System *sys) +{ + int n=0; + int count = 0; + int i =0; + int need_free = 0; + char *msg_buf = g_csm_buf; + struct LocalInterface* lif = NULL; + struct IccpSyncdHDr * msg_hdr; + struct mclag_fdb_info * mac_info; + static time_t last_time = 0; + char* data = &msg_buf[sizeof(struct IccpSyncdHDr)]; + + if(sys == NULL) + return -1; + memset(msg_buf, 0, CSM_BUFFER_SIZE); + + n = read(sys->sync_fd, msg_buf, CSM_BUFFER_SIZE); + if (n <=0) + { + if (last_time == 0 || (time(NULL) - last_time) >= 60) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d read error ret = %d errno = %d ",sys->sync_fd, n, errno); + last_time = time(NULL); + } + + return -1; + } + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg version %d type %d len %d ",msg_hdr->ver , msg_hdr->type, msg_hdr->len ); + if (msg_hdr->ver != 1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "msg version wrong!!!!! "); + return -1; + } + + if (msg_hdr->type != MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "msg type wrong!!!!! "); + return -1; + } + + count =( msg_hdr->len- sizeof(struct IccpSyncdHDr ))/sizeof(struct mclag_fdb_info); + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d ",count ); + for (i =0; ivid, mac_info->mac, mac_info->port_name, mac_info->op_type); + lif = local_if_find_by_name(mac_info->port_name); + + /*if (!lif ||lif->type != IF_T_PORT_CHANNEL)*/ + if (!lif) + continue; + + do_mac_update_from_syncd(mac_info->mac, mac_info->vid, mac_info->port_name, mac_info->type, mac_info->op_type); + } + + return 0; +} + +char * mclagd_ctl_cmd_str(int req_type) +{ + switch (req_type) + { + case INFO_TYPE_DUMP_STATE: + return "dump config"; + case INFO_TYPE_DUMP_ARP: + return "dump arp"; + case INFO_TYPE_DUMP_MAC: + return "dump mac"; + case INFO_TYPE_DUMP_LOCAL_PORTLIST: + return "dump local portlist"; + case INFO_TYPE_DUMP_PEER_PORTLIST: + return "dump peer portlist"; + default: + break; + } + + return "error req type"; +} + +int mclagd_ctl_sock_create() +{ + struct sockaddr_un addr; + struct System* sys = NULL; + struct epoll_event event; + int addr_len; + int ret = 0; + + if ((sys = system_get_instance()) == NULL) + return -1;; + + if(sys->sync_ctrl_fd > 0) + return sys->sync_ctrl_fd; + + sys->sync_ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if(sys->sync_ctrl_fd < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to create mclagd ctl sock\n"); + return sys->sync_ctrl_fd; + } + + unlink(sys->mclagdctl_file_path); + + memset((void*)&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, 107, "%s", sys->mclagdctl_file_path); + addr_len = sizeof(addr.sun_family) + strlen(sys->mclagdctl_file_path); + + if((ret = bind(sys->sync_ctrl_fd, (struct sockaddr*)&addr, addr_len)) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to bind mclagd ctl socket %s:%s\n", sys->mclagdctl_file_path, strerror(errno)); + close(sys->sync_ctrl_fd); + return -1; + } + + if(listen(sys->sync_ctrl_fd, 5) < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to listen unix mclagd ctl socket%s:%s\n", sys->mclagdctl_file_path, strerror(errno)); + close(sys->sync_ctrl_fd); + return -1; + } + + event.data.fd = sys->sync_ctrl_fd; + event.events = EPOLLIN; + epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, sys->sync_ctrl_fd, &event); + FD_SET(sys->sync_ctrl_fd, &(sys->readfd)); + sys->readfd_count++; + + return sys->sync_ctrl_fd; +} + +int mclagd_ctl_sock_accept(int fd) +{ + struct sockaddr_in client_addr; + int client_fd = 0; + unsigned int addr_len = 0; + + client_fd = accept(fd, (struct sockaddr*)&client_addr, &addr_len); + if(client_fd < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "failed to accept a client from mclagdctl\n"); + return -1; + } + + return client_fd; +} + +int mclagd_ctl_sock_read(int fd, unsigned char *r_buf ,int total_len) +{ + int read_len=0; + int ret=0; + struct timeval tv = {0}; + fd_set read_fd; + + while(read_len < total_len) + { + FD_ZERO(&read_fd); + FD_SET(fd, &read_fd); + tv.tv_sec = 5; + tv.tv_usec = 0; + + switch ((ret = select(fd + 1, &read_fd, NULL, NULL, &tv))) + { + case -1: + /* error*/ + case 0: + /* timeout*/ + return -1; + default: + break; + } + if(FD_ISSET(fd, &read_fd)) + ret = read(fd, r_buf + read_len, total_len - read_len); + if(ret <= 0) + { + return -1; + } + read_len += ret; + } + + return read_len; +} + +int mclagd_ctl_sock_write(int fd, unsigned char *w_buf ,int total_len) +{ + int write_len =0; + int ret=0; + + while(write_len < total_len) + { + ret = write(fd, w_buf + write_len, total_len - write_len); + if(ret <= 0) + { + return 0; + } + write_len += ret; + } + + return write_len; +} + +void mclagd_ctl_handle_dump_state(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int state_num = 0; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_mclag_config_dump(&Pbuf, &state_num, mclag_id); + ICCPD_LOG_WARN(__FUNCTION__, "state_num = %d", state_num); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_STATE; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_STATE; + hd->data_len = state_num * sizeof(struct mclagd_state); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_arp(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int arp_num = 0; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_arp_dump(&Pbuf, &arp_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_ARP; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_ARP; + hd->data_len = arp_num * sizeof(struct mclagd_arp_msg); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_mac(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int mac_num = 0; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_mac_dump(&Pbuf, &mac_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_MAC; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_MAC; + hd->data_len = mac_num * sizeof(struct mclagd_mac_msg); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_local_portlist(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int lif_num = 0;; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_local_if_dump(&Pbuf, &lif_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; + hd->data_len = lif_num * sizeof(struct mclagd_local_if); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +void mclagd_ctl_handle_dump_peer_portlist(int client_fd, int mclag_id) +{ + char * Pbuf = NULL; + char buf[512] = {0}; + char tx_buf[MCLAGDCTL_CMD_SIZE] = {0}; + int pif_num = 0; + int index = 0; + int ret = 0; + struct mclagd_reply_hdr *hd = NULL; + + ret = iccp_peer_if_dump(&Pbuf, &pif_num, mclag_id); + if (ret != EXEC_TYPE_SUCCESS) + { + *((int*)buf) = sizeof(struct mclagd_reply_hdr); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = ret; + hd->info_type = INFO_TYPE_DUMP_PEER_PORTLIST; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + + if (Pbuf) + free(Pbuf); + + return; + } + + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_DUMP_PEER_PORTLIST; + hd->data_len = pif_num * sizeof(struct mclagd_peer_if); + *((int*)Pbuf) = (hd->data_len + sizeof(struct mclagd_reply_hdr)); + + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); + + if (Pbuf) + free(Pbuf); + + return; +} + +int mclagd_ctl_interactive_process(int client_fd) +{ + char buf[512] = {0}; + int ret = 0; + + struct mclagdctl_req_hdr* req = NULL; + + if (client_fd < 0) + return -1; + + ret = mclagd_ctl_sock_read(client_fd, buf, sizeof(struct mclagdctl_req_hdr)); + + if (ret < 0) + return -1; + + req = (struct mclagdctl_req_hdr*)buf; + + ICCPD_LOG_WARN(__FUNCTION__, "rcv request %s from mclagdctl", mclagd_ctl_cmd_str(req->info_type)); + + switch (req->info_type) + { + case INFO_TYPE_DUMP_STATE: + mclagd_ctl_handle_dump_state(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_ARP: + mclagd_ctl_handle_dump_arp(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_MAC: + mclagd_ctl_handle_dump_mac(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_LOCAL_PORTLIST: + mclagd_ctl_handle_dump_local_portlist(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_PEER_PORTLIST: + mclagd_ctl_handle_dump_peer_portlist(client_fd, req->mclag_id); + break; + default: + return -1; + } + + return 0; +} + + diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c new file mode 100644 index 000000000000..27a2ad9c00d0 --- /dev/null +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -0,0 +1,789 @@ +/* +* MLACP Sync Infomation Preparation +* mlacp_sync_prepare.c + +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +* +*/ + +#include +#include + +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_fsm.h" +#include "../include/mlacp_tlv.h" +#include "../include/mlacp_link_handler.h" +#include "../include/iccp_ifm.h" + +#define SET_MAC_STR(buf, macArray) \ + snprintf(buf, 64, "%02x:%02x:%02x:%02x:%02x:%02x",\ + macArray[0],macArray[1],macArray[2], \ + macArray[3],macArray[4],macArray[5]); + +#define SYSID_UPDATE_INT 3 /*3 secs*/ + +void update_system_id(struct CSM* csm) +{ + char macaddr[64]; + char ori_macaddr[64]; + struct LocalInterface* lif_po = NULL; + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + char cmd[256]; + int ret = 0; + static int bridge_mac_set = 0; + struct VLAN_ID *vlan = NULL; + + if (!csm) + return; + + if(memcmp(MLACP(csm).system_id, null_mac, ETHER_ADDR_LEN)==0) + return; + + if(memcmp(MLACP(csm).remote_system.system_id, null_mac, ETHER_ADDR_LEN)==0) + return; + + /* don't change mac continously, it needs a little time to process mac*/ + if ((time(NULL)-csm->sysid_update_time) < SYSID_UPDATE_INT) + return; + + time(&csm->sysid_update_time); + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) + { + if(lif_po->type != IF_T_PORT_CHANNEL) + continue; + + /* backup old sysmac*/ + memcpy(lif_po->mac_addr_ori, lif_po->mac_addr, + ETHER_ADDR_LEN); + + /* set new mac*/ + memset(macaddr, 0, 64); + memset(ori_macaddr, 0, 64); + + SET_MAC_STR(ori_macaddr, lif_po->mac_addr); + + if (csm->role_type == STP_ROLE_STANDBY) + { + SET_MAC_STR(macaddr, MLACP(csm).remote_system.system_id); + } + else + { + SET_MAC_STR(macaddr, MLACP(csm).system_id); + } + + if(strcmp(macaddr, ori_macaddr)!= 0) + { + ICCPD_LOG_INFO(__FUNCTION__, + "%s Change the system-id of po%d from %s to %s.", + (csm->role_type == STP_ROLE_STANDBY)?"Standby":"Active", + lif_po->po_id, ori_macaddr, macaddr); + + snprintf(cmd, sizeof cmd, + "ip link set dev %s address %s > /dev/null 2>&1", + lif_po->name, macaddr); + ret = system(cmd); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "%s: Execute command (%s) ret = %d", + __FUNCTION__, cmd, ret); + } + + if(local_if_is_l3_mode(lif_po)) + iccp_set_portchannel_ipadd_mac(lif_po, macaddr ); + else + { + LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) + { + if(!vlan->vlan_itf) + continue; + + /* If the po is under a vlan, update vlan mac*/ + if(local_if_is_l3_mode(vlan->vlan_itf)) + { + snprintf(cmd, sizeof cmd, + "ip link set dev %s address %s > /dev/null 2>&1", + vlan->vlan_itf->name, macaddr); + ret = system(cmd); + + iccp_set_portchannel_ipadd_mac(vlan->vlan_itf, macaddr ); + } + } + } + + /*Set bridge mac, prevent bridge mac changed follow portchannel mac*/ + if(bridge_mac_set == 0) + { + bridge_mac_set = 1; + + snprintf(cmd, sizeof cmd, + "ip link set dev Bridge address %s > /dev/null 2>&1", + ori_macaddr); + + ret = system(cmd); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "%s: Execute command (%s) ret = %d", + __FUNCTION__, cmd, ret); + } + } + } + } + + return; +} + +/***************************************** +* Static Function +* +* ***************************************/ +static int mlacp_fill_icc_header(struct CSM* csm, ICCHdr* icc_hdr, size_t msg_len); + +/***************************************** +* Sync portchannel state and MAC with kernel +* +* ***************************************/ +int mlacp_sync_with_kernel_callback() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); + goto out; + } + + /* traverse all CSM */ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + /* Sync MLAG po state with kernel*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if(local_if->type == IF_T_PORT_CHANNEL) + { + /* sync system info from one port-channel device*/ + if(memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) + { + memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); + MLACP(csm).system_config_changed = 1; + + update_system_id(csm); + + break; + } + } + } + } + +out: + return 0; +} + + +/***************************************** +* Create Sync Request TLV +* +* ***************************************/ +int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = NULL; + mLACPSyncReqTLV* tlv = NULL; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncReqTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPSyncReqTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* mLACP Synchronization Request TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPSyncReqTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_SYNC_REQUEST; + + tlv->req_num = 0; + MLACP(csm).sync_req_num = tlv->req_num; + tlv->c_bit = 1; + tlv->s_bit = 1; + tlv->req_type = 0x3FFF; + tlv->port_num_agg_id = 0; + tlv->actor_key = 0; + + return msg_len; +} + +/***************************************** +* Prprare Sync Data TLV +* +* ***************************************/ +int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*) buf; + mLACPSyncDataTLV* tlv = (mLACPSyncDataTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncDataTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPSyncDataTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* mLACP Synchronization Data TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPSyncDataTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_SYNC_DATA; + + tlv->req_num = MLACP(csm).sync_req_num; + if(end == 0) + tlv->flags = 0x00; + else + tlv->flags = 0x01; + + return msg_len; +} + +/***************************************** +* Prprare Sync System-Config TLV +* +* ***************************************/ +int mlacp_prepare_for_sys_config(struct CSM* csm,char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*) buf; + mLACPSysConfigTLV* tlv = (mLACPSysConfigTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSysConfigTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPSysConfigTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* System Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPSysConfigTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_SYSTEM_CONFIG; + + memcpy(tlv->sys_id, MLACP(csm).system_id, ETHER_ADDR_LEN); + tlv->sys_priority = MLACP(csm).system_priority; + tlv->node_id = MLACP(csm).node_id; + return msg_len; +} + +/*Prprare Sync AggPort-State TLV */ +int mlacp_prepare_for_Aggport_state(struct CSM* csm,char* buf, size_t max_buf_size, struct LocalInterface* local_if) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*) buf; + mLACPAggPortStateTLV* tlv = (mLACPAggPortStateTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggPortStateTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(local_if == NULL) + return -1; + + if(local_if->type != IF_T_PORT_CHANNEL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPAggPortStateTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port State TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPAggPortStateTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_AGGREGATOR_STATE; + + tlv->partner_sys_priority = 0; + tlv->partner_key = 0; + tlv->agg_id = local_if->po_id; + tlv->actor_key = 0; + tlv->agg_state = local_if->state; + + return msg_len; +} + +/***************************************** +* Prprare Sync Purge Port +* +* ***************************************/ +int mlacp_prepare_for_Aggport_config(struct CSM* csm, + char* buf, size_t max_buf_size, + struct LocalInterface* lif, int purge_flag) +{ + ICCHdr* icc_hdr = (ICCHdr*) buf; + mLACPAggConfigTLV* tlv = (mLACPAggConfigTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggConfigTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (mLACPAggConfigTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(mLACPAggConfigTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_AGGREGATOR_CONFIG; + + tlv->agg_id = lif->po_id; + if(purge_flag == 1) + tlv->flags = 0x02; /*purge*/ + else + tlv->flags = 0x1; + tlv->agg_name_len = strlen(lif->name); + memcpy(tlv->agg_name, lif->name, MAX_L_PORT_NAME); + memcpy(tlv->mac_addr, lif->mac_addr, ETHER_ADDR_LEN); + + return msg_len; +} + +/***************************************** +* Preprare Sync MAC-Info TLV +* +* ***************************************/ +int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg) +{ + struct mLACPMACInfoTLV* tlv = NULL; + size_t msg_len = 0; + size_t tlv_len = 0; + ICCHdr* icc_hdr = NULL; + + if (!csm) + return -1; + if (!buf) + return -1; + + tlv_len = sizeof(struct mLACPMACInfoTLV); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return -1; + + /* ICC header */ + memset(buf, 0, max_buf_size); + icc_hdr = (ICCHdr*) buf; + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Prepare for ARP information TLV */ + tlv = (struct mLACPMACInfoTLV*) malloc(tlv_len); + memset(tlv, 0, tlv_len); + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = TLV_T_MLACP_MAC_INFO; + tlv->icc_parameter.len = tlv_len - sizeof(ICCParameter); + tlv->type = mac_msg->op_type; + sprintf(tlv->mac_str, "%s", mac_msg->mac_str); + sprintf(tlv->ifname, "%s", mac_msg->origin_ifname); + tlv->vid = mac_msg->vid; + + /* Fill MAC Information TLV */ + memcpy(&buf[sizeof(ICCHdr)], tlv, tlv_len); + free(tlv); + + #if 1 + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg type = TLV_T_MLACP_MAC_INFO"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s mac = %s, vid = %d, type = %d", mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + #endif + + return msg_len; +} + +/***************************************** +* Preprare Sync ARP-Info TLV +* +* ***************************************/ +int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg) +{ + struct mLACPARPInfoTLV* tlv = NULL; + size_t msg_len = 0; + size_t tlv_len = 0; + ICCHdr* icc_hdr = NULL; + + if (!csm) + return -1; + if (!buf) + return -1; + + tlv_len = sizeof(struct mLACPARPInfoTLV); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return -1; + + /* ICC header */ + memset(buf, 0, max_buf_size); + icc_hdr = (ICCHdr*) buf; + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Prepare for ARP information TLV */ + tlv = (struct mLACPARPInfoTLV*) malloc(tlv_len); + memset(tlv, 0, tlv_len); + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = TLV_T_MLACP_ARP_INFO; + tlv->icc_parameter.len = tlv_len - sizeof(ICCParameter); + tlv->type = arp_msg->op_type; + sprintf(tlv->ifname, "%s", arp_msg->ifname); + tlv->ipv4_addr = arp_msg->ipv4_addr; + memcpy(tlv->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + + /* Fill ARP Information TLV */ + memcpy(&buf[sizeof(ICCHdr)], tlv, tlv_len); + free(tlv); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s msg ifname %s mac =%02x:%02x:%02x:%02x:%02x:%02x ", tlv->ifname, arp_msg->ifname, tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], + tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + ICCPD_LOG_DEBUG(__FUNCTION__, " IP Addr = %s ",show_ip_str( tlv->ipv4_addr)); + + return msg_len; +} + +/***************************************** +* Prprare Send portchannel info +* +* ***************************************/ +int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, + size_t max_buf_size, + struct LocalInterface* port_channel) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = NULL; + struct mLACPPortChannelInfoTLV* tlv = NULL; + size_t msg_len; + size_t tlv_len; + size_t name_len = MAX_L_PORT_NAME; + struct VLAN_ID* vlan_id = NULL; + int num_of_vlan_id = 0; + + if (csm == NULL ) + return -1; + if (buf == NULL ) + return -1; + if (port_channel == NULL ) + return -1; + if (port_channel->type == IF_T_PORT) + return -1; + if ((sys = system_get_instance()) == NULL ) + return -1; + + /* Calculate VLAN ID Length */ + LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next) + if (vlan_id != NULL) num_of_vlan_id++; + + tlv_len = sizeof(struct mLACPPortChannelInfoTLV) + sizeof(struct VLAN_ID) * num_of_vlan_id; + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return -1; + + /* Prepare for port channel info */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (struct mLACPPortChannelInfoTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port Channel Info TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(struct mLACPPortChannelInfoTLV) - sizeof(ICCParameter) + sizeof(struct VLAN_ID) *num_of_vlan_id ; + tlv->icc_parameter.type = TLV_T_MLACP_PORT_CHANNEL_INFO; + tlv->agg_id = port_channel->po_id; + tlv->ipv4_addr = htonl(port_channel->ipv4_addr); + tlv->l3_mode = port_channel->l3_mode; + tlv->po_id = port_channel->po_id; + + if(strlen(port_channel->name) < name_len) + name_len = strlen(port_channel->name); + memcpy(tlv->if_name, port_channel->name, name_len); + tlv->if_name_len = name_len; + tlv->num_of_vlan_id = num_of_vlan_id; + + num_of_vlan_id = 0; + LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next) + { + if (vlan_id != NULL ) + { + tlv->vlanData[num_of_vlan_id].vlan_id = vlan_id->vid; + + num_of_vlan_id++; + ICCPD_LOG_DEBUG(__FUNCTION__, " port channel %d: addr = %s vlan id %d num %d ", port_channel->po_id, show_ip_str( tlv->ipv4_addr), vlan_id->vid, num_of_vlan_id ); + } + } + + ICCPD_LOG_DEBUG(__FUNCTION__, " port channel %d: addr = 0x%08x l3 mode %d", port_channel->po_id, tlv->ipv4_addr, tlv->l3_mode); + + return msg_len; +} + +/***************************************** +* Prprare Send port peerlink info +* +* ***************************************/ +int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, + size_t max_buf_size, + struct LocalInterface* peerlink_port) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = NULL; + struct mLACPPeerLinkInfoTLV* tlv = NULL; + size_t msg_len; + size_t tlv_len; + + if (csm == NULL ) + return -1; + if (buf == NULL ) + return -1; + if (peerlink_port == NULL ) + return -1; + if ((sys = system_get_instance()) == NULL ) + return -1; + + /* Prepare for port channel info */ + memset(buf, 0, max_buf_size); + + tlv_len = sizeof(struct mLACPPeerLinkInfoTLV); + + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) + return -1; + + icc_hdr = (ICCHdr*) buf; + tlv = (struct mLACPPeerLinkInfoTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* Port Channel Info TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = tlv_len - sizeof(ICCParameter) ; + tlv->icc_parameter.type = TLV_T_MLACP_PEERLINK_INFO; + + memcpy(tlv->if_name, peerlink_port->name, MAX_L_PORT_NAME); + tlv->port_type = peerlink_port->type; + + + ICCPD_LOG_DEBUG(__FUNCTION__, " peerlink port info portname %s type = %d", tlv->if_name, tlv->port_type); + + return msg_len; +} + + +/***************************************** +* Prprare Send Heartbeat +* +* ***************************************/ +int mlacp_prepare_for_heartbeat(struct CSM* csm,char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*) buf; + struct mLACPHeartbeatTLV* tlv = (struct mLACPHeartbeatTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPHeartbeatTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (struct mLACPHeartbeatTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* System Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.len = sizeof(struct mLACPHeartbeatTLV) - sizeof(ICCParameter); + tlv->icc_parameter.type = TLV_T_MLACP_HEARTBEAT; + + tlv->heartbeat = 0xFF; + return msg_len; +} + +/***************************************** +* Tool : Prepare ICC Header +* +* ***************************************/ +static int mlacp_fill_icc_header(struct CSM* csm, ICCHdr* icc_hdr, size_t msg_len) +{ + if(csm == NULL || icc_hdr == NULL) + return -1; + + /* ICC header */ + icc_hdr->ldp_hdr.u_bit = 0x0; + icc_hdr->ldp_hdr.msg_type = MSG_T_RG_APP_DATA; + icc_hdr->ldp_hdr.msg_len = msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + icc_hdr->ldp_hdr.msg_id = ICCP_MSG_ID; + ICCP_MSG_ID++; + iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); + + return 0; +} + + +/***************************************** +* Tool : Update System ID +* +* ***************************************/ +void iccp_set_portchannel_ipadd_mac(struct LocalInterface *lif,uint8_t * mac_addr ) +{ + struct IccpSyncdHDr * msg_hdr; + mclag_sub_option_hdr_t * sub_msg; + char msg_buf[4096]; + struct System *sys; + + int src_len = 0,dst_len =0; + sys = system_get_instance(); + if(sys == NULL) + return; + + memset(msg_buf,0,4095); + + msg_hdr = (struct IccpSyncdHDr *)msg_buf; + msg_hdr->ver= 1; + msg_hdr->type = MCLAG_MSG_TYPE_SET_MAC; + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + /*sub msg src*/ + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC; + + src_len = snprintf(sub_msg->data, 512, "%s:%s/%d", lif->name,show_ip_str(htonl(lif->ipv4_addr)),lif->prefixlen); + + sub_msg->op_len = src_len; + + /*sub msg dst */ + msg_hdr->len += sub_msg->op_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_SET_MAC_DST; + + dst_len = strlen(mac_addr); + memcpy(sub_msg->data, mac_addr, dst_len); + + ICCPD_LOG_DEBUG(__FUNCTION__,"lif name %s address %s mac msg data %s %d \n", lif->name , show_ip_str(lif->ipv4_addr), sub_msg->data ,dst_len); + + sub_msg->op_len = dst_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + /*send msg*/ + if(sys->sync_fd) + write(sys->sync_fd,msg_buf, msg_hdr->len); + + return; +} + + diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c new file mode 100644 index 000000000000..f8c8ddbadefa --- /dev/null +++ b/src/iccpd/src/mlacp_sync_update.c @@ -0,0 +1,741 @@ +/******************************************************************************** +* mlacp_sync_update.c +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +* +*******************************************************************************/ +#include +#include + +#include +#include +#include +#include + +#include "../include/system.h" +#include "../include/logger.h" +#include "../include/mlacp_tlv.h" +#include "../include/mlacp_link_handler.h" + +/***************************************** +* Port-Conf Update +* +* ***************************************/ +int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV*sysconf) +{ + /*NOTE + a little tricky, we change the NodeID local side if collision happened first time*/ + if(sysconf->node_id == MLACP(csm).node_id) + MLACP(csm).node_id++; + + memcpy(MLACP(csm).remote_system.system_id, sysconf->sys_id, ETHER_ADDR_LEN); + MLACP(csm).remote_system.system_priority = sysconf->sys_priority; + MLACP(csm).remote_system.node_id = sysconf->node_id; + + update_system_id(csm); + + ICCPD_LOG_DEBUG(__FUNCTION__, " SystemID [%02X:%02X:%02X:%02X:%02X:%02X]. SystemPriority [%d], Remote NodeID [%d], NodeID [%d]", + MLACP(csm).remote_system.system_id[0],MLACP(csm).remote_system.system_id[1],MLACP(csm).remote_system.system_id[2], + MLACP(csm).remote_system.system_id[3],MLACP(csm).remote_system.system_id[4],MLACP(csm).remote_system.system_id[5], + MLACP(csm).remote_system.system_priority, + MLACP(csm).remote_system.node_id, + MLACP(csm).node_id); + + return 0; +} + +/***************************************** +* Port-Conf Update +* +* ***************************************/ +int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf) +{ + struct PeerInterface* pif = NULL; + uint8_t po_active; + uint8_t new_create = 0; + + ICCPD_LOG_DEBUG(__FUNCTION__, " Port name %s, po id %d flag %d MAC[%02x:%02x:%02x:%02x:%02x:%02x] ", + portconf->agg_name,portconf->agg_id, portconf->flags,portconf->mac_addr[0], portconf->mac_addr[1], portconf->mac_addr[2], + portconf->mac_addr[3], portconf->mac_addr[4], portconf->mac_addr[5] ); + + /* Looking for the peer port instance, is any peer if exist?*/ + pif = peer_if_find_by_name(csm, portconf->agg_name); + + /* Process purge*/ + if (portconf->flags & 0x02) + { + /*Purge*/ + if (pif != NULL ) + peer_if_destroy(pif); + else + MLACP(csm).need_to_sync = 1; + /*ICCPD_LOG_INFO("mlacp_fsm", + " Peer port %s is removed from port-channel member.",portconf->port_name);*/ + + return 0; + } + + if(pif == NULL && portconf->flags & 0x01) + { + pif = peer_if_create(csm, portconf->agg_id, IF_T_PORT_CHANNEL); + if(pif == NULL) return -1; + + new_create= 1; + } + + pif->po_id = portconf->agg_id; + memcpy(pif->name, portconf->agg_name, portconf->agg_name_len); + memcpy(pif->mac_addr, portconf->mac_addr, ETHER_ADDR_LEN); + + po_active = (pif->state == PORT_STATE_UP); + update_stp_peer_link(csm, pif, po_active, new_create); + update_peerlink_isolate_from_pif(csm, pif, po_active, new_create); + pif->po_active = po_active; + + return 0; +} + +/***************************************** +* Agg Port-State Update +* +* ***************************************/ +int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) +{ + struct PeerInterface* peer_if = NULL; + uint8_t po_active; + + if(csm == NULL || tlv == NULL) + return -255; + ICCPD_LOG_DEBUG(__FUNCTION__, " po id %d state %d ",tlv->agg_id, tlv->agg_state); + + po_active = (tlv->agg_state == PORT_STATE_UP); + + LIST_FOREACH(peer_if, &(MLACP(csm).pif_list), mlacp_next) + { + if (peer_if->type != IF_T_PORT_CHANNEL) + continue; + + if (peer_if->po_id != tlv->agg_id) + continue; + + peer_if->state = tlv->agg_state; + + update_stp_peer_link(csm, peer_if, po_active, 0); + update_peerlink_isolate_from_pif(csm, peer_if, po_active, 0); + + peer_if->po_active = po_active; + break; + } + + return 0; +} + + /* Delete an entry from the ARP cache. */ +int mlacp_fsm_arp_del(char *ifname, uint32_t ip) +{ + struct arpreq arpreq; + struct sockaddr_in *sin; + struct in_addr ina; + int rc; + int sock_fd = 0; + + ICCPD_LOG_DEBUG(__FUNCTION__,"%s: Del arp entry for IP : %s\n", __FUNCTION__, show_ip_str(ip)); + + if(ifname == NULL || ip == 0) + { + return -1; + } + + /*you must add this becasue some system will return "Invlid argument" + because some argument isn't zero */ + memset(&arpreq, 0, sizeof(struct arpreq)); + + sin = (struct sockaddr_in *) &arpreq.arp_pa; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + ina.s_addr = ip; + memcpy(&sin->sin_addr, (char *) &ina, sizeof(struct in_addr)); + + strncpy(arpreq.arp_dev, ifname, 15); + + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if(sock_fd < 0) + { + return -1; + } + + rc = ioctl(sock_fd, SIOCDARP, &arpreq); + if (rc < 0) + { + close(sock_fd); + return -1; + } + + close(sock_fd); + + return 0; + } + + int getHwAddr(char *buff, char *mac) + { + int i = 0; + unsigned int p[6]; + + if( buff == NULL || mac == NULL ) + { + return -1; + } + + if(sscanf(mac, "%x:%x:%x:%x:%x:%x", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]) < 6) + { + return -1; + } + + for(i = 0; i < 6; i ++) + { + buff[i] = p[i]; + } + + return 0; + } + + /***************************************** + * Recv from peer, MAC-Info Update + * ***************************************/ + int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* tlv) + { + struct Msg* msg = NULL; + struct Msg* msg_send = NULL; + struct MACMsg *mac_msg = NULL, mac_data; + struct LocalInterface* local_if = NULL; + + if (!csm || !tlv) + return -255; + +#if 1 + ICCPD_LOG_INFO(__FUNCTION__, + "Received MAC Info, itf=[%s] vid[%d] MAC[%s] type %d ", + tlv->ifname, tlv->vid, tlv->mac_str, tlv->type); +#endif + + /*Find the interface*/ + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL && strcmp(local_if->name, tlv->ifname) == 0) + { + break; + } + } + + if(!local_if) + { + /*If the interface is not exist, return*/ + return -255; + } + + /* update MAC list*/ + TAILQ_FOREACH(msg, &(MLACP(csm).mac_list), tail) + { + mac_msg = (struct MACMsg*) msg->buf; + if (strcmp(mac_msg->mac_str, tlv->mac_str) == 0 && mac_msg->vid == tlv->vid) + { + if(tlv->type == MAC_SYNC_ADD) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + + /*mac_msg->fdb_type = tlv->fdb_type;*/ + if(strcmp(mac_msg->ifname, tlv->ifname) != 0 || strcmp(mac_msg->origin_ifname, tlv->ifname) != 0) + { + if(mac_msg->fdb_type != MAC_TYPE_STATIC) + { + memcpy(&mac_msg->ifname, tlv->ifname, MAX_L_PORT_NAME); + memcpy(&mac_msg->origin_ifname, tlv->ifname, MAX_L_PORT_NAME); + } + + if(local_if->state == PORT_STATE_DOWN && strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) + { + /*First del the old item*/ + /*del_mac_from_chip(mac_msg);*/ + + /*If local if is down, redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + + /*sleep 10ms, avoid orchagent mix the del event*/ + /*usleep(100000);*/ + + /*Send mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + } + + #if 0 + mac_msg->op_type = MAC_SYNC_ACK; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + /*Reply mac ack message to peer, peer will clean MAC_AGE_PEER flag*/ + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, MAC-msg-list enqueue: %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + } + #endif + } + else if(tlv->type == MAC_SYNC_ACK) + { + /*Clean the MAC_AGE_PEER flag*/ + mac_msg->age_flag &= ~MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ACK, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + } + + break; + } + } + + /* delete/add MAC list*/ + if (msg && tlv->type == MAC_SYNC_DEL) + { + mac_msg->age_flag |= MAC_AGE_PEER; + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + + if(mac_msg->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + { + /*send mac del message to mclagsyncd.*/ + del_mac_from_chip(mac_msg); + + /*If local and peer both aged, del the mac*/ + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + } + else + { + return 0; + } + } + else if (!msg && tlv->type == MAC_SYNC_ADD) + { + mac_msg = (struct MACMsg*) &mac_data; + mac_msg->fdb_type = MAC_TYPE_DYNAMIC; + mac_msg->vid = tlv->vid; + sprintf(mac_msg->mac_str, "%s", tlv->mac_str); + sprintf(mac_msg->ifname, "%s", tlv->ifname); + sprintf(mac_msg->origin_ifname, "%s", tlv->ifname); + mac_msg->age_flag = 0; + + if(local_if->state == PORT_STATE_DOWN) + { + /*If local if is down, redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + } + + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); + /*ICCPD_LOG_INFO(__FUNCTION__, "add mac queue successfully");*/ + + /*Send mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, mac_msg->fdb_type); + + #if 0 + mac_msg->op_type = MAC_SYNC_ACK; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + /*Reply mac ack message to peer, peer will clean MAC_AGE_PEER flag*/ + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + } + #endif + } + } + + return 0; + } + + /* Set an entry in the ARP cache. */ +int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac) +{ + struct arpreq arpreq; + struct sockaddr_in *sin; + struct in_addr ina; + int flags; + int rc; + int sock_fd = 0; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Set arp entry for IP:%s MAC:%s ifname:%s\n", show_ip_str(ip), mac,ifname); + + if(ifname == NULL || ip == 0 || mac == NULL) + { + return -1; + } + + /*you must add this becasue some system will return "Invlid argument" + because some argument isn't zero */ + memset(&arpreq, 0, sizeof(struct arpreq)); + sin = (struct sockaddr_in *) &arpreq.arp_pa; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + ina.s_addr = ip; + memcpy(&sin->sin_addr, (char *) &ina, sizeof(struct in_addr)); + + if(getHwAddr((char *)arpreq.arp_ha.sa_data, mac) < 0) + { + return -1; + } + + strncpy(arpreq.arp_dev, ifname, 15); + + flags = ATF_COM; //note, must set flag, if not,you will get error + + arpreq.arp_flags = flags; + + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if(sock_fd < 0) + { + return -1; + } + + rc = ioctl(sock_fd, SIOCSARP, &arpreq); + if (rc < 0) + { + close(sock_fd); + return -1; + } + + close(sock_fd); + + return 0; +} + +/***************************************** +* Tool : Add ARP Info into ARP list +* +****************************************/ +void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg) +{ + struct ARPMsg *arp_msg = NULL; + + if (!csm) + { + if (msg) + free(msg); + return; + } + if (!msg) + return; + + arp_msg = (struct ARPMsg*) msg->buf; + if (arp_msg->op_type != ARP_SYNC_DEL) + { + time(&arp_msg->update_time); + TAILQ_INSERT_TAIL(&(MLACP(csm).arp_list), msg, tail); + } + + return; +} + +/***************************************** +* ARP-Info Update +* ***************************************/ +int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) +{ + struct Msg* msg = NULL; + struct ARPMsg *arp_msg = NULL, arp_data; + struct LocalInterface* local_if; + struct LocalInterface *peer_link_if = NULL; + struct VLAN_ID *vlan_id_list=NULL; + int set_arp_flag=0; + char mac_str[18] = ""; + + if (!csm || !tlv) + return -255; + + #if 1 + ICCPD_LOG_INFO(__FUNCTION__, + "%s: Received ARP Info," + "itf=[%s] ARP IP[%s],MAC[%02x:%02x:%02x:%02x:%02x:%02x]", + __FUNCTION__, + tlv->ifname, show_ip_str(tlv->ipv4_addr), + tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], + tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + #endif + + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], + tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + + if(strncmp(tlv->ifname,"Vlan",4) == 0) + { + peer_link_if = local_if_find_by_name(csm->peer_itf_name); + + if(!local_if_is_l3_mode(peer_link_if)) + { + /* Is peer-linlk itf belong to a vlan the same as peer?*/ + LIST_FOREACH(vlan_id_list, &(peer_link_if->vlan_list), port_next) + { + if(!vlan_id_list->vlan_itf) + continue; + if(strcmp(vlan_id_list->vlan_itf->name, tlv->ifname)!=0) + continue; + if(!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, + "%s: ==> Find ARP itf on L3 bridge, peer-link %s of %s", + __FUNCTION__, + peer_link_if->name, vlan_id_list->vlan_itf->name); + + /* Peer-link belong to L3 vlan is alive, set the ARP info*/ + set_arp_flag=1; + + break; + } + } + } + + if(set_arp_flag == 0) + { + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) + { + if (local_if->type == IF_T_PORT_CHANNEL) + { + if(!local_if_is_l3_mode(local_if)) + { + /* Is the L2 MLAG itf belong to a vlan the same as peer?*/ + LIST_FOREACH(vlan_id_list, &(local_if->vlan_list), port_next) + { + if(!vlan_id_list->vlan_itf) + continue; + if(strcmp(vlan_id_list->vlan_itf->name, tlv->ifname)!=0) + continue; + if(!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + continue; + + ICCPD_LOG_DEBUG(__FUNCTION__, + "%s: ==> Find ARP itf on L3 bridge, %s of %s", + __FUNCTION__, + local_if->name, vlan_id_list->vlan_itf->name); + break; + } + + if(vlan_id_list && local_if->po_active==1) + { + /* Any po of L3 vlan is alive, set the ARP info*/ + set_arp_flag=1; + break; + } + } + else + { + /* Is the ARP belong to a L3 mode MLAG itf?*/ + if(strcmp(local_if->name, tlv->ifname)==0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, + "%s: ==> Find ARP itf on L3 port-channel, %s", + __FUNCTION__, + local_if->name); + if(local_if->po_active==1) + { + /* po is alive, set the ARP info*/ + set_arp_flag=1; + break; + } + } + else + { + continue; + } + } + } + } + } + + /* set dynamic ARP*/ + if (set_arp_flag == 1) + { + if (tlv->type == ARP_SYNC_ADD) + { + if(mlacp_fsm_arp_set(tlv->ifname, tlv->ipv4_addr, mac_str) < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__,"%s: ARP set for %s %s %s", + __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); + return -1; + } + } + else + { + if(mlacp_fsm_arp_del(tlv->ifname, tlv->ipv4_addr) < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__,"%s: ARP delete for %s %s %s", + __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); + return -1; + } + } + + ICCPD_LOG_DEBUG(__FUNCTION__,"%s: ARP update for %s %s %s", + __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ==> port-channel is not alive", + __FUNCTION__); + /*TODO Set static route through peer-link or just skip it?*/ + } + + /* update ARP list*/ + TAILQ_FOREACH(msg, &(MLACP(csm).arp_list), tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + if (arp_msg->ipv4_addr == tlv->ipv4_addr) + { + /*arp_msg->op_type = tlv->type;*/ + sprintf(arp_msg->ifname, "%s", tlv->ifname); + memcpy(arp_msg->mac_addr, tlv->mac_addr, ETHER_ADDR_LEN); + break; + } + } + + /* delete/add ARP list*/ + if (msg && tlv->type == ARP_SYNC_DEL) + { + TAILQ_REMOVE(&(MLACP(csm).arp_list), msg, tail); + free(msg->buf); free(msg); + ICCPD_LOG_INFO(__FUNCTION__, "%s: del arp queue successfully", + __FUNCTION__); + } + else if (!msg && tlv->type == ARP_SYNC_ADD) + { + arp_msg = (struct ARPMsg*) &arp_data; + sprintf(arp_msg->ifname, "%s", tlv->ifname); + arp_msg->ipv4_addr = tlv->ipv4_addr; + arp_msg->op_type = tlv->type; + memcpy(arp_msg->mac_addr, tlv->mac_addr, ETHER_ADDR_LEN); + if (iccp_csm_init_msg(&msg, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + { + mlacp_enqueue_arp(csm, msg); + ICCPD_LOG_INFO(__FUNCTION__, "%s: add arp queue successfully", + __FUNCTION__); + } + } + + /* remove all ARP msg queue, when receive peer's ARP list at the same time*/ + TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + if (arp_msg->ipv4_addr == tlv->ipv4_addr) break; + } + + while (msg) + { + arp_msg = (struct ARPMsg*) msg->buf; + TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); + free(msg->buf); + free(msg); + TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) + { + arp_msg = (struct ARPMsg*) msg->buf; + if (arp_msg->ipv4_addr == tlv->ipv4_addr) break; + } + } + + return 0; +} + +/***************************************** +* Port-Channel-Info Update +* ***************************************/ +int mlacp_fsm_update_port_channel_info(struct CSM* csm, + struct mLACPPortChannelInfoTLV* tlv) +{ + struct PeerInterface* peer_if = NULL; + struct LocalInterface* local_if = NULL; + struct VLAN_ID* peer_vlan_id = NULL; + int i = 0; + + if (csm == NULL || tlv == NULL ) + return -1; + + LIST_FOREACH(peer_if, &(MLACP(csm).pif_list), mlacp_next) + { + if (peer_if->type != IF_T_PORT_CHANNEL) + continue; + + if (peer_if->po_id != tlv->agg_id) + continue; + + LIST_FOREACH(peer_vlan_id, &(peer_if->vlan_list), port_next) + { + peer_vlan_id->vlan_removed = 1; + } + + /* Record peer info*/ + peer_if->ipv4_addr = ntohl(tlv->ipv4_addr); + peer_if->l3_mode = tlv->l3_mode; + + for (i = 0; i < tlv->num_of_vlan_id; i++) + { + peer_if_add_vlan(peer_if,tlv->vlanData[i].vlan_id); + } + + peer_if_clean_unused_vlan(peer_if); + + iccp_consistency_check(peer_if->name); + + ICCPD_LOG_DEBUG(__FUNCTION__, "port channel info ip %s l3 mode %d", show_ip_str( peer_if->ipv4_addr), peer_if->l3_mode); + break; + } + + return 0; +} + +/***************************************** +* Peerlink port Update +* ***************************************/ +int mlacp_fsm_update_peerlink_info(struct CSM* csm, + struct mLACPPeerLinkInfoTLV* tlv) +{ + if (csm == NULL || tlv == NULL ) + return -1; + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port info from peer"); + + if(csm->peer_link_if->type != tlv->port_type) + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port type of peer %d is not same as local %d !", tlv->port_type, csm->peer_link_if->type); + + /*if(tlv->port_type == IF_T_VXLAN && strncmp(csm->peer_itf_name, tlv->if_name, strlen(csm->peer_itf_name))) + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port is vxlan port and peerlink port at peer %s is not same as local peerlink port %s !",tlv->if_name, csm->peer_itf_name);*/ + + return 0; +} + +/***************************************** +* Heartbeat Update +*****************************************/ +int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv) +{ + if (!csm || !tlv) + return -255; + + time(&csm->heartbeat_update_time); + + return 0; +} + + diff --git a/src/iccpd/src/port.c b/src/iccpd/src/port.c new file mode 100644 index 000000000000..3ebbc3517ef6 --- /dev/null +++ b/src/iccpd/src/port.c @@ -0,0 +1,711 @@ +/* +* port.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include + +#include "../include/logger.h" +#include "../include/port.h" +#include "../include/system.h" +#include "../include/iccp_csm.h" + +/* Ethernet MAC Address setter - set by string. */ +static void ether_mac_set_addr_with_string(uint8_t* macdst, const char* macstr) +{ + char* dupmac = NULL; + char* token = NULL; + unsigned long oct; + int i = 0; + + if(macdst == NULL || macstr == NULL) + return; + + memset(macdst, 0, 6); + + dupmac = strdup(macstr); + + /* tokenize */ + token = strtok(dupmac, " -:"); + oct = strtoul(token, NULL, 16); + if(oct > 255) + oct = 0xff; + macdst[0] = oct; + + for(i=1; i<6; ++i) + { + token = strtok(NULL, " -:"); + if(token == NULL) + { + memset(macdst, 0, 6); + break; + } + oct = strtoul(token, NULL, 16); + if(oct > 255) + oct = 0xff; + macdst[i] = oct; + } + + free(dupmac); + + return; +} + +/* Get the Ethernet MAC Address by interface name. */ +void ether_mac_set_addr_with_if_name(char* name, uint8_t* mac) +{ + char addr_file[64]; + FILE *file_ptr = NULL; + char buf[64]; + + if (!mac || !name) + return; + + memset(addr_file, 0, 64); + snprintf(addr_file, 63, "/sys/class/net/%s/address", name); + + if ((file_ptr = fopen(addr_file, "r"))) + { + memset(buf, 0, 64); + fgets(buf, 63, file_ptr); + fclose(file_ptr); + ether_mac_set_addr_with_string(mac, buf); + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to find device %s from %s", name, addr_file); + } + + return; +} + +void local_if_init(struct LocalInterface* local_if) +{ + if (local_if == NULL) + return; + + memset(local_if, 0, sizeof(struct LocalInterface)); + local_if->po_id = -1; + local_if->po_active = 1; //always guess the po is active + local_if->mlacp_state = MLACP_STATE_INIT; + local_if->type = IF_T_UNKNOW; + local_if->changed = 1; + local_if->port_config_sync = 0; + local_if->is_peer_link = 0; + local_if->is_arp_accept = 0; + local_if->l3_mode = 0; + local_if->state = PORT_STATE_DOWN; + local_if->prefixlen = 32; + local_if->csm = NULL; + local_if->isolate_to_peer_link = 0; + LIST_INIT(&local_if->vlan_list); + + return; +} + +void vlan_info_init(struct VLAN_ID* vlan) +{ + vlan->vid = -1; + vlan->vlan_removed= 0; + vlan->vlan_itf = NULL; + + return; +} + +struct LocalInterface* local_if_create(int ifindex, char* ifname, int type) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + uint8_t mac[ETHER_ADDR_LEN]; + struct CSM* csm; + struct If_info * cif = NULL; + + if(!ifname) + return NULL; + + if (!(sys = system_get_instance())) + return NULL; + + if (ifindex < 0) + return NULL; + + if ((local_if = local_if_find_by_ifindex(ifindex))) + return local_if; + + if (!(local_if = (struct LocalInterface*) malloc(sizeof(struct LocalInterface)))) { + ICCPD_LOG_WARN(__FUNCTION__, "port ifindex = %d, malloc failed", ifindex); + return NULL; + } + + local_if_init(local_if); + local_if->ifindex = ifindex; + local_if->type = type; + + if(local_if->type == IF_T_PORT_CHANNEL) + { + int i; + int len; + len = strlen(ifname); + + for(i=0; i= '0' && ifname[i] <= '9') + break; + + if(i >= len) + return NULL; + + local_if->po_id = atoi(&ifname[i]); + } + + if (ifname) + snprintf(local_if->name, MAX_L_PORT_NAME, "%s", ifname); + + switch (type) + { + case IF_T_PORT_CHANNEL: + break; + case IF_T_PORT: + break; + case IF_T_VLAN: + /* do nothing currently. */ + break; + default: + ICCPD_LOG_WARN(__FUNCTION__, "the type of local interface (%s) is not acceptable", ifname); + if (local_if) + free(local_if); + return NULL; + } + + ICCPD_LOG_INFO(__FUNCTION__, + "Create a local_if = %s ifindex = %d MAC = %02x:%02x:%02x:%02x:%02x:%02x, state = %s", + ifname, local_if->ifindex, local_if->mac_addr[0], local_if->mac_addr[1], local_if->mac_addr[2], + local_if->mac_addr[3], local_if->mac_addr[4], local_if->mac_addr[5], local_if->state ? "down" : "up"); + + LIST_INSERT_HEAD(&(sys->lif_list), local_if, system_next); + + /*Check the intf is peer-link? Only support PortChannel and Ethernet currently*/ + /*When set peer-link, the local-if is probably not created*/ + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if(strcmp(local_if->name, csm->peer_itf_name) == 0) + { + local_if->is_peer_link = 1; + csm->peer_link_if = local_if; + break; + } + /*check the intf is bind with csm*/ + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) + { + if (strcmp(ifname, cif->name) ==0) + mlacp_bind_port_channel_to_csm(csm,ifname); + } + } + + return local_if; +} + +struct LocalInterface* local_if_find_by_name(const char* ifname) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + + if (!ifname) + return NULL; + + if (!(sys = system_get_instance())) + return NULL; + + LIST_FOREACH(local_if, &(sys->lif_list), system_next) + { + if (strcmp(local_if->name, ifname) == 0) + return local_if; + } + + return NULL; +} + +struct LocalInterface* local_if_find_by_ifindex(int ifindex) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return NULL; + + LIST_FOREACH(local_if, &(sys->lif_list), system_next) + { + if(local_if->ifindex == ifindex) + return local_if; + } + + return NULL; +} + +struct LocalInterface* local_if_find_by_po_id(int po_id) +{ + struct System* sys = NULL; + struct LocalInterface* local_if = NULL; + + if((sys = system_get_instance()) == NULL) + return NULL; + + LIST_FOREACH(local_if, &(sys->lif_list), system_next) + { + if(local_if->type == IF_T_PORT_CHANNEL && local_if->po_id == po_id) + return local_if; + } + + return NULL; +} + +static void local_if_vlan_remove(struct LocalInterface *lif_vlan) +{ + struct System *sys = NULL; + struct LocalInterface *lif = NULL; + struct VLAN_ID *vlan = NULL; + + if ((sys = system_get_instance()) != NULL) + { + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + LIST_FOREACH(vlan, &(lif->vlan_list), port_next) + { + if(lif_vlan != vlan->vlan_itf) + continue; + + vlan->vlan_itf = NULL; + } + } + } + + return; +} + +static void local_if_po_remove(struct LocalInterface *lif_po) +{ + struct System *sys = NULL; + struct CSM *csm = NULL; + struct LocalInterface *lif = NULL; + + /* remove all po member*/ + if ((sys = system_get_instance()) != NULL) + { + csm = lif_po->csm; + if (csm) + { + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + if (lif->type != IF_T_PORT) continue; + if (lif->po_id != lif_po->po_id) continue; + + mlacp_unbind_local_if(lif); + } + } + } + + return; +} + +static void local_if_remove(struct LocalInterface *lif) +{ + mlacp_unbind_local_if(lif); + lif->po_id = -1; + + return; +} + +void local_if_destroy(char *ifname) +{ + struct LocalInterface* lif = NULL; + struct CSM *csm = NULL; + struct System *sys = NULL; + + if (!(sys = system_get_instance())) + return; + + lif = local_if_find_by_name(ifname); + if (!lif) return; + + ICCPD_LOG_WARN(__FUNCTION__, "destroy interface %s, %d\n", lif->name, lif->ifindex); + + if (lif->type == IF_T_VLAN) + local_if_vlan_remove(lif); + else if (lif->type == IF_T_PORT_CHANNEL) + local_if_po_remove(lif); + else + local_if_remove(lif); + + csm = lif->csm; + if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + goto to_mlacp_purge; + else + goto to_sys_purge; + +to_sys_purge: + /* sys purge */ + LIST_REMOVE(lif, system_next); + if (lif->csm) LIST_REMOVE(lif, mlacp_next); + LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next); + return; + +to_mlacp_purge: + /* sys & mlacp purge */ + LIST_REMOVE(lif, system_next); + LIST_REMOVE(lif, mlacp_next); + LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next); + LIST_INSERT_HEAD(&(MLACP(csm).lif_purge_list), lif, mlacp_purge_next); + return; +} + +int local_if_is_l3_mode(struct LocalInterface* local_if) +{ + int ret = 0; + + if (local_if == NULL) + return 0; + + if (local_if->ipv4_addr !=0) + ret = 1; + + return ret; +} + +void local_if_change_flag_clear(void) +{ + struct System* sys = NULL; + struct LocalInterface* lif = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(lif, &(sys->lif_list), system_next) + { + if (lif->changed == 1) + { + lif->changed = 0; + } + } + + return; +} + +void local_if_purge_clear(void) +{ + struct System* sys = NULL; + struct LocalInterface* lif = NULL; + + if((sys = system_get_instance()) == NULL) + return; + + /* destroy purge if*/ + while (!LIST_EMPTY(&(sys->lif_purge_list))) + { + lif = LIST_FIRST(&(sys->lif_purge_list)); + ICCPD_LOG_DEBUG(__FUNCTION__, "purge %s", lif->name); + LIST_REMOVE(lif, system_purge_next); + if (lif->mlacp_purge_next.le_next!=0 && lif->mlacp_purge_next.le_prev!=0) + LIST_REMOVE(lif, mlacp_purge_next); + local_if_del_all_vlan(lif); + free(lif); + } + LIST_INIT(&(sys->lif_purge_list)); + + return; +} + +void local_if_finalize(struct LocalInterface* lif) +{ + if (lif == NULL) + return; + + local_if_del_all_vlan(lif); + + free(lif); + + return; +} + +struct PeerInterface* peer_if_create(struct CSM* csm, + int peer_if_number, int type) +{ + struct PeerInterface* peer_if = NULL; + + /* check csm*/ + if (csm == NULL) + return NULL; + + /* check id*/ + if (peer_if_number < 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "peer interface id < 0"); + return NULL; + } + + /* check type*/ + if (type != IF_T_PORT && type != IF_T_PORT_CHANNEL) + { + ICCPD_LOG_WARN(__FUNCTION__, + "the type(%) of peer interface(%d) is not acceptable", + type, peer_if_number); + return NULL; + } + + /* create a new peer if*/ + if ((peer_if = (struct PeerInterface*) malloc(sizeof(struct PeerInterface))) == NULL) + { + ICCPD_LOG_WARN(__FUNCTION__, "peer port id = %d, malloc failed", peer_if_number); + return NULL; + } + memset(peer_if, 0, sizeof(struct PeerInterface)); + + if (type == IF_T_PORT) + { + peer_if->ifindex = peer_if_number; + peer_if->type = IF_T_PORT; + peer_if->csm = csm; + } + else if (type == IF_T_PORT_CHANNEL) + { + peer_if->ifindex = peer_if_number; + peer_if->type = IF_T_PORT_CHANNEL; + } + + LIST_INSERT_HEAD(&(MLACP(csm).pif_list), peer_if, mlacp_next); + + return peer_if; +} + +struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name) +{ + struct System* sys = NULL; + struct PeerInterface* peer_if = NULL; + + if ((sys = system_get_instance()) == NULL) + return NULL; + + if (csm == NULL) + return NULL; + + LIST_FOREACH(peer_if, &(csm->app_csm.mlacp.pif_list), mlacp_next) + { + if (strcmp(peer_if->name, name) == 0) + return peer_if; + } + + return NULL; +} + +void peer_if_del_all_vlan(struct PeerInterface* pif) +{ + struct VLAN_ID *pvlan = NULL; + + while (!LIST_EMPTY(&(pif->vlan_list))) + { + pvlan = LIST_FIRST(&(pif->vlan_list)); + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", + pvlan->vid, pif->name); + LIST_REMOVE(pvlan, port_next); + free(pvlan); + } + + return; +} + +void peer_if_destroy(struct PeerInterface* pif) +{ + ICCPD_LOG_WARN(__FUNCTION__, "destroy peer's interface %s, %d\n", + pif->name, pif->ifindex); + + /* destroy if*/ + LIST_REMOVE(pif, mlacp_next); + peer_if_del_all_vlan(pif); + + free(pif); + return; +} + +int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) +{ + struct VLAN_ID *vlan = NULL; + char vlan_name[16] = ""; + + sprintf(vlan_name, "Vlan%d", vid); + + /* traverse 1 time */ + LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) + { + if(vlan->vid == vid) + break; + } + + if (!vlan) + { + vlan = (struct VLAN_ID*) malloc(sizeof(struct VLAN_ID)); + if(!vlan) + return -1; + + ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d on %s", vid, local_if->name); + local_if->port_config_sync = 1; + LIST_INSERT_HEAD(&(local_if->vlan_list), vlan, port_next); + } + + vlan_info_init(vlan); + vlan->vid = vid; + vlan->vlan_removed = 0; + vlan->vlan_itf = local_if_find_by_name(vlan_name); + return 0; +} + +void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid) +{ + struct VLAN_ID *vlan = NULL; + + /* traverse 1 time */ + LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) + { + if(vlan->vid == vid) + break; + } + + if(vlan != NULL) + { + LIST_REMOVE(vlan, port_next); + free(vlan); + local_if->port_config_sync = 1; + } + + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d on %s", vid, local_if->name); + + return; +} + +void local_if_del_all_vlan(struct LocalInterface* lif) +{ + struct VLAN_ID* vlan = NULL; + + while (!LIST_EMPTY(&(lif->vlan_list))) + { + vlan = LIST_FIRST(&(lif->vlan_list)); + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d on %s", vlan->vid, lif->name); + LIST_REMOVE(vlan, port_next); + free(vlan); + } + + return; +} + +/* Add VLAN from peer-link*/ +int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) +{ + struct VLAN_ID *peer_vlan = NULL; + char vlan_name[16] = ""; + + sprintf(vlan_name, "Vlan%d", vlan_id); + + /* traverse 1 time */ + LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) + { + if (peer_vlan->vid == vlan_id) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "update VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); + break; + } + } + + if(!peer_vlan) + { + peer_vlan = (struct VLAN_ID*) malloc(sizeof(struct VLAN_ID)); + if(!peer_vlan) + return -1; + + ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d from peer's %s", vlan_id, peer_if->name); + LIST_INSERT_HEAD(&(peer_if->vlan_list), peer_vlan, port_next); + } + + vlan_info_init(peer_vlan); + peer_vlan->vid = vlan_id; + peer_vlan->vlan_removed = 0; + + return 0; +} + +/* Used by sync update*/ +int peer_if_clean_unused_vlan(struct PeerInterface* peer_if) +{ + struct VLAN_ID *peer_vlan = NULL; + struct VLAN_ID *peer_vlan_next = NULL; + + /* traverse 1 time */ + LIST_FOREACH(peer_vlan_next, &(peer_if->vlan_list), port_next) + { + if(peer_vlan != NULL) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); + LIST_REMOVE(peer_vlan, port_next); + free(peer_vlan); + peer_vlan = NULL; + + } + if (peer_vlan_next->vlan_removed == 1) + peer_vlan = peer_vlan_next; + } + + if(peer_vlan != NULL) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); + LIST_REMOVE(peer_vlan, port_next); + free(peer_vlan); + } + + return 0; +} + +int set_sys_arp_accept_flag(char* ifname, int flag) +{ + FILE *file_ptr = NULL; + char cmd[64]; + char arp_file[64]; + char buf[2]; + int result = -1; + + memset(arp_file, 0, 64); + snprintf(arp_file, 63, "/proc/sys/net/ipv4/conf/%s/arp_accept", ifname); + if (!(file_ptr = fopen(arp_file, "r"))) + { + ICCPD_LOG_DEBUG(__func__, "Failed to find device %s from %s", ifname, arp_file); + return result; + } + + fgets(buf, sizeof(buf), file_ptr); + if (atoi(buf) == flag) + result = 0; + else + { + memset(cmd, 0, 64); + snprintf(cmd, 63, "echo %d > /proc/sys/net/ipv4/conf/%s/arp_accept", flag, ifname); + if (system(cmd)) + ICCPD_LOG_DEBUG(__func__, "Failed to execute cmd = %s", flag, cmd); + } + + fclose(file_ptr); + return result; +} diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c new file mode 100644 index 000000000000..9c8a7b0292ab --- /dev/null +++ b/src/iccpd/src/scheduler.c @@ -0,0 +1,639 @@ +/* +* scheduler.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../include/logger.h" +#include "../include/system.h" +#include "../include/scheduler.h" +#include "../include/iccp_csm.h" + + +/****************************************************** + * + * Global Variable + * + ******************************************************/ + +static int session_conn_thread_lock(pthread_mutex_t *conn_mutex) +{ + return 1; /*pthread_mutex_lock(conn_mutex);*/ +} + +static int session_conn_thread_trylock(pthread_mutex_t *conn_mutex) +{ + return 0 ;/*pthread_mutex_trylock(conn_mutex);*/ +} + +static int session_conn_thread_unlock(pthread_mutex_t *conn_mutex) +{ + return 1;/* pthread_mutex_unlock(conn_mutex);*/ +} + +static void heartbeat_check(struct CSM *csm) +{ + if (csm->heartbeat_update_time == 0) + { + time(&csm->heartbeat_update_time); + return; + } + + if( (time(NULL) - csm->heartbeat_update_time) > HEARTBEAT_TIMEOUT_SEC) + { + /* hearbeat timeout*/ + ICCPD_LOG_INFO(__FUNCTION__, "iccpd connection timeout (heartbeat)"); + scheduler_session_disconnect_handler(csm); + } + + return; +} + +static void heartbeat_update(struct CSM *csm) +{ + if(csm->sock_fd > 0) + { + heartbeat_check(csm); + } + + return; +} + +/* Transit FSM of all connections */ +static int scheduler_transit_fsm() +{ + struct CSM* csm = NULL; + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return -1; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + heartbeat_update(csm); + iccp_csm_transit(csm); + app_csm_transit(csm); + mlacp_fsm_transit(csm); + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE && (time(NULL) - sys->csm_trans_time) >= 60) + { + iccp_get_fdb_change_from_syncd(); + sys->csm_trans_time = time(NULL); + } + } + + local_if_change_flag_clear(); + local_if_purge_clear(); + + return 1; +} + +/* Receive packets call back function */ +int scheduler_csm_read_callback(struct CSM* csm) +{ + struct Msg* msg = NULL; + /*peer message*/ + char *peer_msg = g_csm_buf; + LDPHdr* ldp_hdr = (LDPHdr*)peer_msg; + char* data = &peer_msg[sizeof(LDPHdr)]; + size_t data_len = 0; + size_t pos = 0; + int recv_len=0, len=0, retval; + + if (csm->sock_fd <= 0) + return -1; + + memset(peer_msg, 0, CSM_BUFFER_SIZE); + + recv_len = 0; + while(recv_len != sizeof(LDPHdr)) + { + len = recv(csm->sock_fd, peer_msg+recv_len, sizeof(LDPHdr)-recv_len, 0); + if (len == -1) + { + perror("recv(). Error"); + goto recv_err; + } + else if (len == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer disconnect"); + goto recv_err; + } + recv_len += len; + /*usleep(100);*/ + } + + data_len = ldp_hdr->msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; + pos = 0; + while(data_len > 0) + { + recv_len = recv(csm->sock_fd, &data[pos], data_len, 0); + if (recv_len == -1) { + perror("continue recv(). Error"); + goto recv_err; + } + else if (recv_len == 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Peer disconnect"); + goto recv_err; + } + data_len -= recv_len; + pos += recv_len; + /*usleep(100);*/ + } + + retval = iccp_csm_init_msg(&msg, peer_msg, ldp_hdr->msg_len + MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); + if (retval == 0) + { + iccp_csm_enqueue_msg(csm, msg); + ++csm->icc_msg_in_count; + } + else + ++csm->i_msg_in_count; + + return 1; + +recv_err: + scheduler_session_disconnect_handler(csm); + return -1; +} + +/* Handle server accept client */ +int scheduler_server_accept() +{ + int new_fd; + int ret = -1; + struct CSM* csm = NULL; + struct System* sys = NULL; + struct sockaddr_in client_addr; + socklen_t addr_len; + + if ((sys = system_get_instance()) == NULL ) + { + return -1; + } + if(sys->server_fd <= 0) + { + return -1; + } + + addr_len = sizeof(struct sockaddr_in); + new_fd = accept(sys->server_fd, (struct sockaddr *) &client_addr, &addr_len); + if (new_fd == -1) + { + goto reject_client; + } + else + { + csm = system_get_csm_by_peer_ip(inet_ntoa(client_addr.sin_addr)); + if(!csm) + { + /* can't find csm with peer ip*/ + ICCPD_LOG_INFO(__FUNCTION__, "csm null with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); + goto reject_client; + } + + if(csm->sock_fd > 0) + { + /* peer already connected*/ + ICCPD_LOG_INFO(__FUNCTION__, "csm sock is connected with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); + goto reject_client; + } + + if((ret = scheduler_check_csm_config(csm)) < 0) + { + /* csm config error*/ + ICCPD_LOG_INFO(__FUNCTION__, "csm config error with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); + goto reject_client; + } + } + + /* Accept*/ + goto accept_client; + +reject_client: + if(new_fd >= 0) close(new_fd); + return -1; + +accept_client: + session_conn_thread_lock(&csm->conn_mutex); + ICCPD_LOG_INFO(__FUNCTION__, "Server Accept, SocketFD [%d], %p", new_fd, csm); + + struct epoll_event event; + int err; + event.data.fd = new_fd; + event.events = EPOLLIN; + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, new_fd, &event); + if(err) + { + session_conn_thread_unlock(&csm->conn_mutex); + goto reject_client; + } + + csm->sock_fd = new_fd; + csm->current_state = ICCP_NONEXISTENT; + FD_SET(new_fd, &(sys->readfd)); + sys->readfd_count ++; + session_conn_thread_unlock(&csm->conn_mutex); + return 0; +} + +/* scheduler initialization */ +void scheduler_init() +{ + struct System* sys = NULL; + + if (!(sys = system_get_instance())) + return; + + /*Get kernel interface and port */ + iccp_sys_local_if_list_get_init(); + + /*Get kernel vlan info */ + iccp_get_if_vlan_info_from_netlink(); + iccp_sys_local_if_list_get_addr(); + + /*Interfaces must be created before this func called*/ + iccp_config_from_file(sys->config_file_path); + + /*Get kernel ARP info */ + iccp_arp_get_init(); + + if(iccp_connect_syncd() < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, syncd info socket connect fail", + __FUNCTION__, __LINE__); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, syncd info socket connect success", + __FUNCTION__, __LINE__); + } + + if (mclagd_ctl_sock_create() < 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclagd ctl info socket connect fail", + __FUNCTION__, __LINE__); + } + + return; +} + +/* Thread fetch to call */ +void scheduler_loop() +{ + struct System* sys = NULL; + int result; + + if ((sys = system_get_instance()) == NULL) + return; + + while(1) + { + if(sys->sync_fd <= 0) + { + iccp_connect_syncd(); + } + + /*handle socket slelect event ,If no message received, it will block 0.1s*/ + iccp_handle_events(sys); + /*csm, app state machine transit */ + scheduler_transit_fsm(); + /*get netlink info again when error happens */ + iccp_netlink_sync_again(); + } + + return; +} + +/* Scheduler start while loop */ +void scheduler_start() +{ + mlacp_sync_with_kernel_callback(); + + scheduler_loop(); + + return; +} + +/* Scheduler tear down */ +void scheduler_finalize() { + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return; + + syncd_info_close(); + + log_finalize(); + + ICCPD_LOG_INFO(__FUNCTION__, "Scheduler is terminated."); + + return; +} + +void* session_client_conn_handler(struct CSM *csm) +{ + struct System* sys = NULL; + struct sockaddr_in peer_addr; + int connFd=-1, connStat=-1; + struct timeval con_tv; + socklen_t len = sizeof(con_tv); + + /* Lock the thread*/ + session_conn_thread_lock(&csm->conn_mutex); + + sys = system_get_instance(); + if(!sys) + goto conn_fail; + + /* Create sock*/ + connFd = socket(PF_INET, SOCK_STREAM, 0); + bzero(&peer_addr, sizeof(peer_addr)); + peer_addr.sin_family = PF_INET; + peer_addr.sin_port = htons(ICCP_TCP_PORT); + peer_addr.sin_addr.s_addr = inet_addr(csm->peer_ip); + if (connFd == -1) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer IP:%s Socket FD creation failed.", + csm->peer_ip); + goto conn_fail; + } + + /* Set connect timeout secs*/ + con_tv.tv_sec = 0; + con_tv.tv_usec = CONNECT_TIMEOUT_MSEC*1000; + if (setsockopt(connFd, SOL_SOCKET, SO_SNDTIMEO, &con_tv, len) == -1) + { + ICCPD_LOG_INFO(__FUNCTION__, "Set socket timeout fail"); + } + + /* Try conn*/ + ICCPD_LOG_INFO(__FUNCTION__, "Connecting. peer ip = [%s], %p", csm->peer_ip, csm); + connStat = connect(connFd, (struct sockaddr*) &(peer_addr), sizeof(peer_addr)); + ICCPD_LOG_INFO(__FUNCTION__, "Connection. fd = [%d], status = [%d], %p", + connFd, connStat, csm); + + if (connStat != 0) + { + /* Conn Fail*/ + goto conn_fail; + } + else + { + /* Conn OK*/ + struct epoll_event event; + int err; + event.data.fd = connFd; + event.events = EPOLLIN; + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, connFd, &event); + if(err) + goto conn_fail; + csm->sock_fd = connFd; + FD_SET(connFd, &(sys->readfd)); + sys->readfd_count++; + ICCPD_LOG_INFO(__FUNCTION__, "Connect to server %s sucess .", csm->peer_ip); + goto conn_ok; + } + +conn_fail: + if(connFd >= 0) + { + csm->sock_fd = -1; + close(connFd); + } +conn_ok: + time(&csm->connTimePrev); + session_conn_thread_unlock(&csm->conn_mutex); + return; +} + +/* Create socket connect to peer */ +int scheduler_prepare_session(struct CSM* csm) +{ + int ret = -1; + uint32_t local_ip = 0; + uint32_t peer_ip = 0; + + /* Init time_t*/ + if (csm->connTimePrev == 0) + { + time(&csm->connTimePrev); + } + + /* Don't conn to svr continously*/ + if((time(NULL) - csm->connTimePrev) < CONNECT_INTERVAL_SEC) + { + goto no_time_update; + } + + /* Already conn?*/ + if(csm->sock_fd > 0) + { + goto time_update; + } + + if ((ret = scheduler_check_csm_config(csm)) < 0) + goto time_update; + + /* Who is client*/ + local_ip = inet_addr(csm->sender_ip); + peer_ip = inet_addr(csm->peer_ip); + if(local_ip > peer_ip) + { + goto time_update; + } + else if(local_ip == peer_ip) + { + ICCPD_LOG_WARN("connect", + "Sender IP is as the same as the peer IP. " + "This must be fixed before connection is built."); + goto time_update; + } + + if(session_conn_thread_trylock(&csm->conn_mutex) == 0) + { + session_client_conn_handler(csm); + session_conn_thread_unlock(&csm->conn_mutex); + } + +time_update: + time(&csm->connTimePrev); + return 0; + +no_time_update: + return 0; +} + +/* Server socket initialization */ +void scheduler_server_sock_init() +{ + int optval = 1; + struct System* sys = NULL; + struct sockaddr_in svr_addr; + + if ((sys = system_get_instance()) == NULL) + return; + + sys->server_fd = socket(PF_INET, SOCK_STREAM, 0); + bzero(&(svr_addr), sizeof(svr_addr)); + svr_addr.sin_family = PF_INET; + svr_addr.sin_port = htons(ICCP_TCP_PORT); + svr_addr.sin_addr.s_addr = INADDR_ANY; + + if (sys->server_fd == -1) + { + ICCPD_LOG_ERR(__FUNCTION__, "Server Socket FD creation failed."); + return; + } + + if (setsockopt(sys->server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) + { + ICCPD_LOG_INFO(__FUNCTION__,"Set socket option failed. Error"); + /*return;*/ + } + + /* set_nonblocking(sys->server_fd);*/ + + if (bind(sys->server_fd, (struct sockaddr*) &(svr_addr), sizeof(svr_addr)) < 0) + { + ICCPD_LOG_INFO(__FUNCTION__,"Bind socket failed. Error"); + return; + } + + if (listen(sys->server_fd, MAX_ACCEPT_CONNETIONS) == -1) + { + ICCPD_LOG_INFO(__FUNCTION__,"Listen failed. Error"); + return; + } + + ICCPD_LOG_INFO(__FUNCTION__, "Server socket init done."); + + return; +} + +int iccp_get_server_sock_fd() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL) + return 0; + + return sys->server_fd; +} + +/* Server socket initialization */ +int scheduler_check_csm_config(struct CSM* csm) +{ + int ret = 1; + struct LocalInterface* lif = NULL; + struct System* sys = NULL; + + if((sys = system_get_instance()) == NULL) + return -1; + + if (csm == NULL ) + return -1; + + if(csm->mlag_id <= 0) + ret = -1; + else if (strlen(csm->peer_itf_name) <= 0) + ret = -1; + else if (strlen(csm->peer_ip) <= 0) + ret = -1; + else if (strlen(csm->sender_ip) <= 0) + ret = -1; + else if ((lif=local_if_find_by_name(csm->peer_itf_name)) == NULL) + ret = -1; + else + { + lif->is_peer_link = 1; + csm->peer_link_if = lif; + } + + if(ret == -1) + ICCPD_LOG_INFO(__FUNCTION__, "mclag config is not complete or conflicting, please check!"); + /* Decide STP role*/ + iccp_csm_stp_role_count(csm); + + return ret; +} + +int scheduler_unregister_sock_read_event_callback(struct CSM* csm) +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL ) + return -1; + + if (csm == NULL ) + { + return -2; + } + + FD_CLR(csm->sock_fd, &(sys->readfd)); + + return 0; +} + +void scheduler_session_disconnect_handler(struct CSM* csm) +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL ) + return ; + + struct epoll_event event; + + if (csm == NULL) + return ; + + session_conn_thread_lock(&csm->conn_mutex); + scheduler_unregister_sock_read_event_callback(csm); + if(csm->sock_fd > 0) + { + event.data.fd = csm->sock_fd; + event.events = EPOLLIN; + epoll_ctl(sys->epoll_fd, EPOLL_CTL_DEL, csm->sock_fd, &event); + + close(csm->sock_fd); + csm->sock_fd = -1; + } + + mlacp_peerlink_disconn_handler(csm); + MLACP(csm).current_state = MLACP_STATE_INIT; + iccp_csm_status_reset(csm, 0); + time(&csm->connTimePrev); + session_conn_thread_unlock(&csm->conn_mutex); + + return; +} diff --git a/src/iccpd/src/system.c b/src/iccpd/src/system.c new file mode 100644 index 000000000000..1f30d4ae20a0 --- /dev/null +++ b/src/iccpd/src/system.c @@ -0,0 +1,185 @@ +/* +* system.c +* +* Copyright(c) 2016-2019 Nephos/Estinet. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, see . +* +* The full GNU General Public License is included in this distribution in +* the file called "COPYING". +* +* Maintainer: jianjun, grace Li from nephos +*/ + +#include + +#include "../include/iccp_csm.h" +#include "../include/logger.h" +#include "../include/iccp_netlink.h" + +/* Singleton */ +struct System* system_get_instance() +{ + static struct System* sys = NULL; + + if (sys == NULL ) + { + sys = (struct System*) malloc(sizeof(struct System)); + if (sys == NULL ) + { + return NULL ; + } + system_init(sys); + } + + return sys; +} + +/* System instance initialization */ +void system_init(struct System* sys) +{ + if (sys == NULL ) + return; + + sys->server_fd = -1; + sys->sync_fd = -1; + sys->sync_ctrl_fd = -1; + sys->arp_receive_fd = -1; + sys->epoll_fd = -1; + LIST_INIT(&(sys->csm_list)); + LIST_INIT(&(sys->lif_list)); + LIST_INIT(&(sys->lif_purge_list)); + + sys->log_file_path = strdup("/var/log/iccpd.log"); + sys->cmd_file_path = strdup("/var/run/iccpd/iccpd.vty"); + sys->config_file_path = strdup("/etc/iccpd/iccpd.conf"); + sys->mclagdctl_file_path = strdup("/var/run/iccpd/mclagdctl.sock"); + sys->pid_file_fd = 0; + sys->telnet_port = 2015; + FD_ZERO(&(sys->readfd)); + sys->readfd_count = 0; + sys->csm_trans_time = 0; + sys->need_sync_team_again = 0; + sys->need_sync_netlink_again = 0; + scheduler_server_sock_init(); + iccp_system_init_netlink_socket(); + iccp_init_netlink_event_fd(sys); +} + +/* System instance tear down */ +void system_finalize() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + struct LocalInterface* local_if = NULL; + + if ((sys = system_get_instance()) == NULL ) + return; + + ICCPD_LOG_INFO(__FUNCTION__, "System resource pool is destructing."); + + while (!LIST_EMPTY(&(sys->csm_list))) + { + csm = LIST_FIRST(&(sys->csm_list)); + iccp_csm_finalize(csm); + } + + /* Release all port objects */ + while (!LIST_EMPTY(&(sys->lif_list))) + { + local_if = LIST_FIRST(&(sys->lif_list)); + local_if_finalize(local_if); + } + while (!LIST_EMPTY(&(sys->lif_purge_list))) + { + local_if = LIST_FIRST(&(sys->lif_list)); + local_if_finalize(local_if); + } + + if (sys->log_file_path != NULL ) + free(sys->log_file_path); + if (sys->cmd_file_path != NULL ) + free(sys->cmd_file_path); + if (sys->config_file_path != NULL ) + free(sys->config_file_path); + if (sys->pid_file_fd > 0) + close(sys->pid_file_fd); + if(sys->server_fd > 0) + close(sys->server_fd); + if(sys->sync_fd > 0) + close(sys->sync_fd); + if(sys->sync_ctrl_fd > 0) + close(sys->sync_ctrl_fd); + if(sys->arp_receive_fd > 0) + close(sys->arp_receive_fd); + if(sys->epoll_fd) + close(sys->epoll_fd); + + free(sys); + ICCPD_LOG_INFO(__FUNCTION__, "System resource pool destructed successfully..."); +} + +struct CSM* system_create_csm() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return NULL ; + + /* Create a new csm */ + csm = (struct CSM*) malloc(sizeof(struct CSM)); + if (csm == NULL ) + return NULL; + else + memset(csm, 0, sizeof(struct CSM)); + iccp_csm_init(csm); + LIST_INSERT_HEAD(&(sys->csm_list), csm, next); + + return csm; +} + +/* Get connect state machine instance by peer ip */ +struct CSM* system_get_csm_by_peer_ip(const char* peer_ip) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return NULL ; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (strcmp(csm->peer_ip, peer_ip) == 0) + return csm; + } + + return NULL ; +} + +struct CSM* system_get_csm_by_mlacp_id(int id) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return NULL ; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if (csm->app_csm.mlacp.id == id) + return csm; + } + + return NULL ; +} From db361fdd6f783a839eabb77e4fb20c2164b05d66 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 31 Jan 2019 23:36:00 -0800 Subject: [PATCH 03/23] remove binary file --- src/iccpd/src/mclagdctl/mclagdctl | Bin 46856 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 src/iccpd/src/mclagdctl/mclagdctl diff --git a/src/iccpd/src/mclagdctl/mclagdctl b/src/iccpd/src/mclagdctl/mclagdctl deleted file mode 100755 index 5e878b720e6d0f14e94aa1dc0b26416216fc7c5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46856 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 vCdyzGD)mK~kb=E;Dftt+{WKjez< Date: Thu, 14 Feb 2019 01:43:37 -0800 Subject: [PATCH 04/23] remove unused dockerfile update docker-iccpd to stretch-based container Signed-off-by: shine.chen --- dockers/docker-iccpd/Dockerfile | 30 ------------------------------ dockers/docker-iccpd/Dockerfile.j2 | 2 +- rules/docker-iccpd.mk | 4 +++- 3 files changed, 4 insertions(+), 32 deletions(-) delete mode 100644 dockers/docker-iccpd/Dockerfile diff --git a/dockers/docker-iccpd/Dockerfile b/dockers/docker-iccpd/Dockerfile deleted file mode 100644 index d932ff955561..000000000000 --- a/dockers/docker-iccpd/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -FROM docker-config-engine - -## Make apt-get non-interactive -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update - -RUN apt-get install -f -y libdbus-1-3 libdaemon0 libjansson4 - -## Install redis-tools dependencies -## TODO: implicitly install dependencies -RUN apt-get -y install libjemalloc1 -RUN apt-get -y install libpython2.7 -RUN apt-get -y install ebtables -RUN apt-get install -f kmod - -COPY \ -debs/libnl-3-200_3.2.27-2_amd64.deb debs/libnl-route-3-200_3.2.27-2_amd64.deb debs/libnl-genl-3-200_3.2.27-2_amd64.deb debs/libnl-nf-3-200_3.2.27-2_amd64.deb debs/libhiredis0.13_0.13.3-2_amd64.deb debs/libnl-cli-3-200_3.2.27-2_amd64.deb debs/libswsscommon_1.0.0_amd64.deb debs/libsairedis_1.0.0_amd64.deb debs/libsaimetadata_1.0.0_amd64.deb debs/libteam5_1.26-1_amd64.deb debs/python-swsscommon_1.0.0_amd64.deb debs/swss_1.0.0_amd64.deb debs/redis-tools_3.2.4-1~bpo8+1_amd64.deb debs/iccpd_0.0.5_amd64.deb debs/ - -RUN dpkg -i \ -debs/libnl-3-200_3.2.27-2_amd64.deb debs/libnl-route-3-200_3.2.27-2_amd64.deb debs/libnl-genl-3-200_3.2.27-2_amd64.deb debs/libnl-nf-3-200_3.2.27-2_amd64.deb debs/libhiredis0.13_0.13.3-2_amd64.deb debs/libnl-cli-3-200_3.2.27-2_amd64.deb debs/libswsscommon_1.0.0_amd64.deb debs/libsairedis_1.0.0_amd64.deb debs/libsaimetadata_1.0.0_amd64.deb debs/libteam5_1.26-1_amd64.deb debs/python-swsscommon_1.0.0_amd64.deb debs/swss_1.0.0_amd64.deb debs/redis-tools_3.2.4-1~bpo8+1_amd64.deb debs/iccpd_0.0.5_amd64.deb - -COPY ["start.sh", "iccpd.sh", "/usr/bin/"] -COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] -COPY ["iccpd.j2", "/usr/share/sonic/templates/"] - -RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y -RUN rm -rf /debs - -ENTRYPOINT ["/usr/bin/supervisord"] \ No newline at end of file diff --git a/dockers/docker-iccpd/Dockerfile.j2 b/dockers/docker-iccpd/Dockerfile.j2 index 7f09c6b8ccd3..0b6b200dfb6d 100644 --- a/dockers/docker-iccpd/Dockerfile.j2 +++ b/dockers/docker-iccpd/Dockerfile.j2 @@ -1,4 +1,4 @@ -FROM docker-config-engine +FROM docker-config-engine-stretch ## Make apt-get non-interactive ENV DEBIAN_FRONTEND=noninteractive diff --git a/rules/docker-iccpd.mk b/rules/docker-iccpd.mk index c15e95694ba0..3d79a2236b82 100644 --- a/rules/docker-iccpd.mk +++ b/rules/docker-iccpd.mk @@ -3,10 +3,12 @@ DOCKER_ICCPD = docker-iccpd.gz $(DOCKER_ICCPD)_PATH = $(DOCKERS_PATH)/docker-iccpd $(DOCKER_ICCPD)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(ICCPD) -$(DOCKER_ICCPD)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE) +$(DOCKER_ICCPD)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_STRETCH) SONIC_DOCKER_IMAGES += $(DOCKER_ICCPD) SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ICCPD) +SONIC_STRETCH_DOCKERS += $(DOCKER_ICCPD) + $(DOCKER_ICCPD)_CONTAINER_NAME = iccpd $(DOCKER_ICCPD)_RUN_OPT += --net=host --privileged -t $(DOCKER_ICCPD)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro From 7b99945798b793bd0500c27e7af9196a50da65be Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 14 Feb 2019 22:59:21 -0800 Subject: [PATCH 05/23] minor fix for isolation port setting Signed-off-by: shine.chen --- src/iccpd/src/mlacp_link_handler.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index e18743b18a0d..74cba7c2e827 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -391,16 +391,9 @@ void update_peerlink_isolate_from_all_csm_lif ( sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC; - if(csm->peer_link_if->type == IF_T_PORT) - { - src_len= strlen(csm->peer_link_if->name); - memcpy(sub_msg->data, csm->peer_link_if->name, src_len); - } - else - { - src_len= strlen(csm->peer_link_if->portchannel_member_buf); - memcpy(sub_msg->data, csm->peer_link_if->portchannel_member_buf, src_len); - } + src_len= strlen(csm->peer_link_if->name); + memcpy(sub_msg->data, csm->peer_link_if->name, src_len); + sub_msg->op_len = src_len; /*sub msg dst */ From 68621fd2fcab979a2ec925cba2b861c1367ec33f Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 7 Mar 2019 03:37:19 -0800 Subject: [PATCH 06/23] iccpd docker would start on demand Signed-off-by: shine.chen --- files/build_templates/iccpd.service.j2 | 1 - 1 file changed, 1 deletion(-) diff --git a/files/build_templates/iccpd.service.j2 b/files/build_templates/iccpd.service.j2 index 17017ef1549e..bf8ae828c68f 100644 --- a/files/build_templates/iccpd.service.j2 +++ b/files/build_templates/iccpd.service.j2 @@ -10,4 +10,3 @@ ExecStart=/usr/bin/{{docker_container_name}}.sh attach ExecStop=/usr/bin/{{docker_container_name}}.sh stop [Install] -WantedBy=multi-user.target From 027a8df7b357af0015a87c04624029380aa99378 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 4 Jul 2019 23:57:13 -0700 Subject: [PATCH 07/23] Add x attribute on mclagdctl file Signed-off-by: shine.chen --- dockers/docker-iccpd/base_image_files/mclagdctl | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 dockers/docker-iccpd/base_image_files/mclagdctl diff --git a/dockers/docker-iccpd/base_image_files/mclagdctl b/dockers/docker-iccpd/base_image_files/mclagdctl old mode 100644 new mode 100755 From 1a9fb62a0ff947438d642c25c27ac1ac1e0c4a8b Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 11 Jul 2019 02:01:38 -0700 Subject: [PATCH 08/23] add warm-reboot support for MCLAG Signed-off-by: shine.chen --- src/iccpd/include/iccp_csm.h | 1 + src/iccpd/include/iccp_netlink.h | 1 + src/iccpd/include/mlacp_sync_update.h | 1 + src/iccpd/include/mlacp_tlv.h | 8 + src/iccpd/include/msg_format.h | 6 +- src/iccpd/include/scheduler.h | 1 + src/iccpd/include/system.h | 7 + src/iccpd/src/app_csm.c | 88 ++--- src/iccpd/src/cmd_option.c | 70 ++-- src/iccpd/src/iccp_cli.c | 134 +++---- src/iccpd/src/iccp_cmd.c | 12 +- src/iccpd/src/iccp_cmd_show.c | 135 +++---- src/iccpd/src/iccp_consistency_check.c | 22 +- src/iccpd/src/iccp_csm.c | 267 +++++++------- src/iccpd/src/iccp_ifm.c | 226 ++++++------ src/iccpd/src/iccp_main.c | 141 ++++++-- src/iccpd/src/iccp_netlink.c | 473 +++++++++++++------------ src/iccpd/src/logger.c | 36 +- src/iccpd/src/mclagdctl/mclagdctl.c | 34 +- src/iccpd/src/mlacp_fsm.c | 21 ++ src/iccpd/src/mlacp_link_handler.c | 69 ++-- src/iccpd/src/mlacp_sync_prepare.c | 42 +++ src/iccpd/src/mlacp_sync_update.c | 12 + src/iccpd/src/scheduler.c | 83 ++++- src/iccpd/src/system.c | 13 +- 25 files changed, 1122 insertions(+), 781 deletions(-) diff --git a/src/iccpd/include/iccp_csm.h b/src/iccpd/include/iccp_csm.h index 40d72e8137a7..514252fe0c51 100644 --- a/src/iccpd/include/iccp_csm.h +++ b/src/iccpd/include/iccp_csm.h @@ -102,6 +102,7 @@ struct CSM { time_t connTimePrev; time_t heartbeat_send_time; time_t heartbeat_update_time; + time_t peer_warm_reboot_time; char peer_itf_name[IFNAMSIZ]; char peer_ip[INET_ADDRSTRLEN]; char sender_ip[INET_ADDRSTRLEN]; diff --git a/src/iccpd/include/iccp_netlink.h b/src/iccpd/include/iccp_netlink.h index edd3bd5747dd..8defb999138b 100644 --- a/src/iccpd/include/iccp_netlink.h +++ b/src/iccpd/include/iccp_netlink.h @@ -36,6 +36,7 @@ int iccp_get_port_member_list(struct LocalInterface* lif); void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg); void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg); int iccp_system_init_netlink_socket(); +void iccp_system_dinit_netlink_socket(); int iccp_init_netlink_event_fd(struct System *sys); int iccp_handle_events(struct System * sys); void update_if_ipmac_on_standby(struct LocalInterface* lif_po); diff --git a/src/iccpd/include/mlacp_sync_update.h b/src/iccpd/include/mlacp_sync_update.h index f9f8d8bc2802..7e09360fbd6c 100644 --- a/src/iccpd/include/mlacp_sync_update.h +++ b/src/iccpd/include/mlacp_sync_update.h @@ -39,6 +39,7 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv); int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv); +int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv); void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg); int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf); diff --git a/src/iccpd/include/mlacp_tlv.h b/src/iccpd/include/mlacp_tlv.h index 90ea0dc1f076..480390bcec7a 100644 --- a/src/iccpd/include/mlacp_tlv.h +++ b/src/iccpd/include/mlacp_tlv.h @@ -379,6 +379,14 @@ struct mLACPHeartbeatTLV { uint8_t heartbeat; }__attribute__ ((packed)); +/* +* NOS: Warm_reboot +*/ +struct mLACPWarmbootTLV { + ICCParameter icc_parameter; + uint8_t warmboot; +}__attribute__ ((packed)); + enum ARP_OP_TYPE { ARP_SYNC_LIF, ARP_SYNC_ADD, diff --git a/src/iccpd/include/msg_format.h b/src/iccpd/include/msg_format.h index 62ef786914f0..4b7a091ffa0b 100644 --- a/src/iccpd/include/msg_format.h +++ b/src/iccpd/include/msg_format.h @@ -93,12 +93,12 @@ /* Self define Feature */ #define TLV_T_MLACP_ORPHAN_PORT 0x1033 //not yet #define TLV_T_MLACP_PORT_CHANNEL_INFO 0x1034 -#define TLV_T_MLACP_PEERLINK_INFO 0x1035 +#define TLV_T_MLACP_PEERLINK_INFO 0x1035 #define TLV_T_MLACP_ARP_INFO 0x1036 #define TLV_T_MLACP_STP_INFO 0x1037//no support #define TLV_T_MLACP_MAC_INFO 0x1038 - -#define TLV_T_MLACP_LIST_END 0x1039 //list end +#define TLV_T_MLACP_WARMBOOT_FLAG 0x1039 +#define TLV_T_MLACP_LIST_END 0x104a //list end /* Debug */ static char* get_tlv_type_string(int type) diff --git a/src/iccpd/include/scheduler.h b/src/iccpd/include/scheduler.h index 156b82247242..d791434d1760 100644 --- a/src/iccpd/include/scheduler.h +++ b/src/iccpd/include/scheduler.h @@ -54,5 +54,6 @@ void scheduler_server_sock_init(); int scheduler_csm_read_callback(struct CSM* csm) ; int iccp_get_server_sock_fd(); int scheduler_server_accept(); +int iccp_receive_signal_handler(struct System* sys); #endif /* SCHEDULER_H_ */ diff --git a/src/iccpd/include/system.h b/src/iccpd/include/system.h index 93acd806a789..4608eb936e6e 100644 --- a/src/iccpd/include/system.h +++ b/src/iccpd/include/system.h @@ -42,6 +42,8 @@ #define VLAN_PREFIX "Vlan" #define VXLAN_TUNNEL_PREFIX "VTTNL" +#define WARM_REBOOT 1 + struct CSM; #ifndef MAX_BUFSIZE @@ -62,6 +64,11 @@ struct System { int route_sock_seq; struct nl_sock * genric_event_sock; struct nl_sock * route_event_sock; + + int sig_pipe_r; + int sig_pipe_w; + int warmboot_start; + int warmboot_exit; /* Info List*/ LIST_HEAD(csm_list, CSM) csm_list; diff --git a/src/iccpd/src/app_csm.c b/src/iccpd/src/app_csm.c index de092c6527f6..26475a05c109 100644 --- a/src/iccpd/src/app_csm.c +++ b/src/iccpd/src/app_csm.c @@ -51,27 +51,27 @@ void app_csm_init(struct CSM* csm, int all) { if (csm == NULL ) return; - + APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); - + if(all) { bzero(&(csm->app_csm), sizeof(struct AppCSM)); APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); } - + csm->app_csm.current_state = APP_NONEXISTENT; csm->app_csm.rx_connect_msg_id = 0; csm->app_csm.tx_connect_msg_id = 0; csm->app_csm.invalid_msg_id = 0; csm->app_csm.invalid_msg = 0; csm->app_csm.nak_msg = 0; - + mlacp_init(csm, all); } /* Application State Machine instance tear down */ -void app_csm_finalize(struct CSM* csm) +void app_csm_finalize(struct CSM* csm) { mlacp_finalize(csm); } @@ -81,9 +81,9 @@ void app_csm_transit(struct CSM* csm) { if (csm == NULL ) return; - + /* torn down event */ - if (csm->app_csm.current_state != APP_NONEXISTENT && csm->sock_fd <= 0) + if (csm->app_csm.current_state != APP_NONEXISTENT && csm->sock_fd <= 0) { csm->app_csm.current_state = APP_NONEXISTENT; return; @@ -106,7 +106,7 @@ void app_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) int tlv = -1; int i = 0; - if (csm == NULL ) + if (csm == NULL ) { if (msg != NULL ) free(msg); @@ -114,7 +114,7 @@ void app_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) } if (msg == NULL ) return; - + icc_hdr = (ICCHdr*) msg->buf; param = (ICCParameter*) &msg->buf[sizeof(struct ICCHdr)]; *(uint16_t *)param = ntohs(*(uint16_t *)param); @@ -137,13 +137,13 @@ void app_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) break; } } - + if(tlv > TLV_T_MLACP_CONNECT && tlv <= TLV_T_MLACP_MAC_INFO) mlacp_enqueue_msg(csm, msg); else TAILQ_INSERT_TAIL(&(csm->app_csm.app_msg_list), msg, tail); - } - else + } + else { /* This packet is not for me, ignore it. */ ICCPD_LOG_DEBUG(__FUNCTION__, "Ignore the packet with msg_type = %d", icc_hdr->ldp_hdr.msg_type); @@ -154,13 +154,13 @@ void app_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) struct Msg* app_csm_dequeue_msg(struct CSM* csm) { struct Msg* msg = NULL; - - if (!TAILQ_EMPTY(&(csm->app_csm.app_msg_list))) + + if (!TAILQ_EMPTY(&(csm->app_csm.app_msg_list))) { msg = TAILQ_FIRST(&(csm->app_csm.app_msg_list)); TAILQ_REMOVE(&(csm->app_csm.app_msg_list), msg, tail); } - + return msg; } @@ -170,7 +170,7 @@ int app_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) ICCHdr* icc_hdr = (ICCHdr*) buf; NAKTLV* naktlv = (NAKTLV*) &buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); - + ICCPD_LOG_DEBUG(__FUNCTION__, " Response NAK"); memset(buf, 0, max_buf_size); icc_hdr->ldp_hdr.u_bit = 0x0; @@ -185,7 +185,7 @@ int app_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) naktlv->iccp_status_code = htonl(STATUS_CODE_ICCP_REJECTED_MSG); naktlv->rejected_msg_id = htonl(csm->app_csm.invalid_msg_id); - + return msg_len; } @@ -193,15 +193,15 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) { struct LocalInterface* lifp = NULL; struct LocalInterface* lif_po = NULL; - + if (csm == NULL || lif == NULL) return -1; - + if (lif->csm == csm) return 0; - + /* remove purge from the csm*/ - do + do { LIST_FOREACH(lifp, &(MLACP(csm).lif_purge_list), mlacp_purge_next) { @@ -211,55 +211,55 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) if (lifp) LIST_REMOVE(lifp, mlacp_purge_next); } while (lifp); - + /* already join csm?*/ LIST_FOREACH(lifp, &(MLACP(csm).lif_list), mlacp_next) { if (lifp == lif) return 0; } - + /* join another csm beofre? remove from csm*/ if (lif->csm != NULL) mlacp_unbind_local_if(lif); - + /* join new csm*/ LIST_INSERT_HEAD(&(MLACP(csm).lif_list), lif, mlacp_next); lif->csm = csm; if (lif->type == IF_T_PORT_CHANNEL) lif->port_config_sync = 1; - + ICCPD_LOG_INFO(__FUNCTION__, "%s: MLACP bind on csm %p", lif->name, csm); if (lif->type == IF_T_PORT_CHANNEL) return 0; - + /* if join a po member, needs to check po joined also*/ LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) { if (lif_po->type == IF_T_PORT_CHANNEL && lif_po->po_id == lif->po_id) { /*if join a po member, may swss restart, reset portchannel ip mac to mclagsyncd*/ - update_if_ipmac_on_standby(lif_po); + update_if_ipmac_on_standby(lif_po); return 0; } } - - if (lif_po == NULL) + + if (lif_po == NULL) { lif_po = local_if_find_by_po_id(lif->po_id); - if (lif_po == NULL) + if (lif_po == NULL) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to find port_channel instance for %d.", lif->po_id); return -1; } - + lif_po->csm = csm; LIST_INSERT_HEAD(&(MLACP(csm).lif_list), lif_po, mlacp_next); - lif_po->port_config_sync = 1; + lif_po->port_config_sync = 1; ICCPD_LOG_INFO(__FUNCTION__, "Add port_channel %d into local_if_list in CSM %p.", lif->po_id, csm); } - + return 0; } @@ -267,19 +267,19 @@ int mlacp_unbind_local_if(struct LocalInterface* lif) { if (lif == NULL ) return -1; - + if (lif->csm == NULL ) return 0; - + ICCPD_LOG_INFO(__FUNCTION__, "%s: MLACP un-bind from csm %p", lif->name, lif->csm); LIST_REMOVE(lif, mlacp_next); - + if (MLACP(lif->csm).current_state == MLACP_STATE_EXCHANGE && lif->type == IF_T_PORT_CHANNEL) LIST_INSERT_HEAD(&(MLACP(lif->csm).lif_purge_list), lif, mlacp_purge_next); if (lif->type == IF_T_PORT) lif->po_id = -1; lif->csm = NULL; - + return 0; } @@ -287,22 +287,22 @@ int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname) { struct System* sys = NULL; struct LocalInterface *lif_po = NULL; - + sys = system_get_instance(); if(sys == NULL) return 0; - + if (csm == NULL) return 0; - + /* bind po first*/ lif_po = local_if_find_by_name(ifname); - if (lif_po) + if (lif_po) { mlacp_bind_local_if(csm, lif_po); - iccp_get_port_member_list(lif_po); + iccp_get_port_member_list(lif_po); } - else + else { ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance .", @@ -312,7 +312,7 @@ int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname) /* process link state handler after attaching it.*/ mlacp_mlag_link_add_handler(csm, lif_po); - + /*ICCPD_LOG_WARN(tag, "po%d active = %d\n", po_id, po_is_active);*/ return 0; } diff --git a/src/iccpd/src/cmd_option.c b/src/iccpd/src/cmd_option.c index 21be3ceebd59..aaef80924d19 100644 --- a/src/iccpd/src/cmd_option.c +++ b/src/iccpd/src/cmd_option.c @@ -23,7 +23,7 @@ #include "../include/cmd_option.h" -struct CmdOption* cmd_option_find(struct CmdOptionParser* parser, char* opt_name) +struct CmdOption* cmd_option_find(struct CmdOptionParser* parser, char* opt_name) { struct CmdOption* opt = NULL; @@ -39,7 +39,7 @@ struct CmdOption* cmd_option_find(struct CmdOptionParser* parser, char* opt_name return NULL; } -void cmd_option_delete(struct CmdOption* opt) +void cmd_option_delete(struct CmdOption* opt) { if (opt == NULL) return; @@ -54,7 +54,7 @@ void cmd_option_delete(struct CmdOption* opt) free(opt); } -struct CmdOption* cmd_option_add(struct CmdOptionParser* parser, char* opt_name) +struct CmdOption* cmd_option_add(struct CmdOptionParser* parser, char* opt_name) { struct CmdOption* opt = NULL; @@ -63,22 +63,22 @@ struct CmdOption* cmd_option_add(struct CmdOptionParser* parser, char* opt_name) if ((opt = cmd_option_find(parser, opt_name)) != NULL) return opt; - if ((opt = (struct CmdOption*) malloc(sizeof(struct CmdOption))) == NULL) + if ((opt = (struct CmdOption*) malloc(sizeof(struct CmdOption))) == NULL) { strerror(errno); - } - else + } + else { opt->option = opt_name; opt->parameter = NULL; opt->desc = NULL; LIST_INSERT_HEAD(&(parser->option_list), opt, next); } - + return opt; } -static void cmd_option_register(struct CmdOptionParser* parser, char* syntax, char* desc) +static void cmd_option_register(struct CmdOptionParser* parser, char* syntax, char* desc) { char buf[OPTION_MAX_LEN]; struct CmdOption* opt = NULL; @@ -104,13 +104,13 @@ static void cmd_option_register(struct CmdOptionParser* parser, char* syntax, ch desc_copy = strdup(desc); if ((opt = cmd_option_find(parser, opt_name)) != NULL) goto failed; - if ((opt = cmd_option_add(parser, opt_name)) == NULL) + if ((opt = cmd_option_add(parser, opt_name)) == NULL) { goto failed; } opt->parameter = param; opt->desc = desc_copy; - + return; failed: @@ -124,7 +124,7 @@ static void cmd_option_register(struct CmdOptionParser* parser, char* syntax, ch free(opt); } -void cmd_option_parser_init(struct CmdOptionParser* parser) +void cmd_option_parser_init(struct CmdOptionParser* parser) { if (parser == NULL) return; @@ -136,17 +136,17 @@ void cmd_option_parser_init(struct CmdOptionParser* parser) cmd_option_register(parser, "-h", "Show the usage."); } -void cmd_option_parser_finalize(struct CmdOptionParser* parser) +void cmd_option_parser_finalize(struct CmdOptionParser* parser) { while (!LIST_EMPTY(&(parser->option_list))) { - struct CmdOption* opt = NULL; + struct CmdOption* opt = NULL; opt = LIST_FIRST(&(parser->option_list)); cmd_option_delete(opt); - } + } } -void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_name) +void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_name) { char buf[MSG_LEN]; struct CmdOption* opt = NULL; @@ -156,7 +156,7 @@ void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_nam fprintf(stdout, "Usage: %s [Options]\n", prog_name); fprintf(stdout, "\n"); fprintf(stdout, "Options:\n"); - LIST_FOREACH(opt, &(parser->option_list), next) + LIST_FOREACH(opt, &(parser->option_list), next) { index = 0; begin = 0; @@ -168,10 +168,10 @@ void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_nam else snprintf(buf, MSG_LEN - 1, "%s", opt->option); fprintf(stdout, "%24s ", buf); - while (index < strlen(opt->desc)) + while (index < strlen(opt->desc)) { while (index < strlen(opt->desc) - && opt->desc[index] != '\n' && length < 49) + && opt->desc[index] != '\n' && length < 49) { ++index; ++length; @@ -181,7 +181,7 @@ void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_nam if (length == 49 && index < strlen(opt->desc) && opt->desc[index] != '\n' && opt->desc[index - 1] != ' ' - && opt->desc[index] != ' ') + && opt->desc[index] != ' ') { buf[length] = '-'; buf[length + 1] = '\0'; @@ -189,11 +189,11 @@ void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_nam if (length < 49) ++index; begin = index; length = 0; - if (first_line != 0) + if (first_line != 0) { fprintf(stdout, "%-52s\n", buf); first_line = 0; - } + } else fprintf(stdout, "%28c%-52s\n", ' ', buf); } @@ -201,7 +201,7 @@ void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_nam } } -int cmd_option_parser_parse(struct CmdOptionParser* parser, int argc, char* argv[]) +int cmd_option_parser_parse(struct CmdOptionParser* parser, int argc, char* argv[]) { int index = 1; struct CmdOption* opt = NULL; @@ -212,21 +212,21 @@ int cmd_option_parser_parse(struct CmdOptionParser* parser, int argc, char* argv if (parser == NULL) return -255; - while (index < argc) + while (index < argc) { opt_name = argv[index]; opt = cmd_option_find(parser, opt_name); - if (opt == NULL) + if (opt == NULL) { fprintf(stderr, "Unknown option %s, skip it.\n", opt_name); ++index; continue; } - - if (opt->parameter != NULL) + + if (opt->parameter != NULL) { ++index; - if (index >= argc) + if (index >= argc) { fprintf(stderr, "Error: Insufficient parameter for option %s\n", opt_name); cmd_option_parser_dump_usage(parser, argv[0]); @@ -234,29 +234,29 @@ int cmd_option_parser_parse(struct CmdOptionParser* parser, int argc, char* argv } val = argv[index]; } - - if (strncmp(opt_name, "-h", 2) == 0) + + if (strncmp(opt_name, "-h", 2) == 0) { cmd_option_parser_dump_usage(parser, argv[0]); return -1; } - + if (strncmp(opt_name, "-l", 2) == 0) parser->log_file_path = val; - - if (strncmp(opt_name, "-p", 2) == 0) + + if (strncmp(opt_name, "-p", 2) == 0) { num = atoi(val); if (num > 0 && num < 65535) parser->telnet_port = num; - } + } else if (strncmp(opt_name, "-c", 2) == 0) parser->console_log = 1; else fprintf(stderr, "Unknown option name %s, skip it.\n", opt_name); - + ++index; } - + return 0; } diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c index 3f8474be828f..f95a127ed007 100644 --- a/src/iccpd/src/iccp_cli.c +++ b/src/iccpd/src/iccp_cli.c @@ -35,9 +35,9 @@ int set_mc_lag_id( struct CSM *csm, uint16_t id) { if (!csm) return -1; - + ICCPD_LOG_INFO(__FUNCTION__, "Set mlag-id : %d", id); - + /* Mlag-ID, RG-ID, MLACP-ID Temporary let the three id be the same*/ csm->mlag_id = id; @@ -49,14 +49,14 @@ int set_mc_lag_id( struct CSM *csm, uint16_t id) int unset_mc_lag_id( struct CSM *csm, uint16_t id) { if (!csm) return -1; - + /* Mlag-ID, RG-ID, MLACP-ID*/ csm->mlag_id = 0; csm->iccp_info.icc_rg_id = 0; csm->app_csm.mlacp.id = 0; - + iccp_csm_finalize(csm); - + return 0; } @@ -76,26 +76,26 @@ int set_peer_link(int mid, const char* ifname) ICCPD_LOG_ERR(__FUNCTION__, "Peer-link is %s, must be Ethernet or PortChannel or VTTNL(Vxlan tunnel)", ifname); return -1; } - + csm = system_get_csm_by_mlacp_id(mid); if(csm == NULL) return -1; if (len > IFNAMSIZ) return -1; - - if (strlen(csm->peer_itf_name) > 0) + + if (strlen(csm->peer_itf_name) > 0) { - if(strcmp(csm->peer_itf_name, ifname) == 0) + if(strcmp(csm->peer_itf_name, ifname) == 0) { ICCPD_LOG_INFO(__FUNCTION__, "Peer-link not be changed"); return 0; } - else + else { ICCPD_LOG_INFO(__FUNCTION__, "Change peer-link : %s -> %s", csm->peer_itf_name, ifname); - + scheduler_session_disconnect_handler(csm); - + if(csm->peer_link_if) { csm->peer_link_if->is_peer_link = 0; @@ -103,27 +103,27 @@ int set_peer_link(int mid, const char* ifname) } } } - else + else { ICCPD_LOG_INFO(__FUNCTION__, "Set mlag %d peer-link : %s", csm->mlag_id,ifname); } - + memset(csm->peer_itf_name, 0, IFNAMSIZ); memcpy(csm->peer_itf_name, ifname, len); - + /* update peer-link link handler*/ lif = local_if_find_by_name(csm->peer_itf_name); - if (lif) + if (lif) { csm->peer_link_if = lif; - lif->is_peer_link = 1; + lif->is_peer_link = 1; MLACP(csm).system_config_changed = 1; - + if(lif->type == IF_T_PORT_CHANNEL) iccp_get_port_member_list(lif); } - + return 0; } @@ -132,7 +132,7 @@ int unset_peer_link(int mid) struct CSM* csm = NULL; csm = system_get_csm_by_mlacp_id(mid); - if(csm == NULL) return -1; + if(csm == NULL) return -1; if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { @@ -142,10 +142,10 @@ int unset_peer_link(int mid) /* Clean all port block*/ peerlink_port_isolate_cleanup(csm); - + /* update peer-link link handler*/ scheduler_session_disconnect_handler(csm); - + /* clean peer-link*/ memset(csm->peer_itf_name, 0, IFNAMSIZ); if(csm->peer_link_if) @@ -154,7 +154,7 @@ int unset_peer_link(int mid) csm->peer_link_if = NULL; MLACP(csm).system_config_changed = 1; } - + return 0; } @@ -165,18 +165,18 @@ int set_local_address(int mid, const char* addr) { struct CSM* csm = NULL; size_t len = 0; - + csm = system_get_csm_by_mlacp_id(mid); if(csm == NULL) return -1; if (addr == NULL) return -1; - + if (strlen(csm->sender_ip) > 0) { if (strcmp(csm->sender_ip, addr) == 0) { ICCPD_LOG_INFO(__FUNCTION__, "Local-address not be changed"); return 0; } else { - ICCPD_LOG_INFO(__FUNCTION__, "Change local-address : %s -> %s", + ICCPD_LOG_INFO(__FUNCTION__, "Change local-address : %s -> %s", csm->sender_ip, addr); scheduler_session_disconnect_handler(csm); } @@ -184,29 +184,29 @@ int set_local_address(int mid, const char* addr) else { ICCPD_LOG_INFO(__FUNCTION__, "Set local-address : %s", addr); } - + len = strlen(addr); memset(csm->sender_ip, 0, INET_ADDRSTRLEN); memcpy(csm->sender_ip, addr, len); memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); memcpy(csm->iccp_info.sender_name, addr, len); - + return 0; } int unset_local_address(int mid) { struct CSM* csm = NULL; - + csm = system_get_csm_by_mlacp_id(mid); if(csm == NULL) return -1; memset(csm->sender_ip, 0, INET_ADDRSTRLEN); memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); - + /* reset link*/ scheduler_session_disconnect_handler(csm); - + return 0; } @@ -217,50 +217,50 @@ int set_peer_address(int mid, const char* addr) { struct CSM* csm = NULL; size_t len = 0; - + csm = system_get_csm_by_mlacp_id(mid); if(csm == NULL) return -1; if(addr == NULL) return -1; - + len = strlen(addr); - - if (strlen(csm->peer_ip) > 0) + + if (strlen(csm->peer_ip) > 0) { - if(strcmp(csm->peer_ip, addr) == 0) + if(strcmp(csm->peer_ip, addr) == 0) { ICCPD_LOG_INFO(__FUNCTION__, "Peer-address not be changed"); return 0; } - else + else { - ICCPD_LOG_INFO(__FUNCTION__, "Change peer-address : %s -> %s", + ICCPD_LOG_INFO(__FUNCTION__, "Change peer-address : %s -> %s", csm->peer_ip, addr); scheduler_session_disconnect_handler(csm); } } - else + else { ICCPD_LOG_INFO(__FUNCTION__, "Set peer-address : %s", addr); } - + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); memcpy(csm->peer_ip, addr, len); - + return 0; } int unset_peer_address(int mid) { struct CSM* csm = NULL; - + csm = system_get_csm_by_mlacp_id(mid); if(csm == NULL) return -1; - + memset(csm->peer_ip, 0, INET_ADDRSTRLEN); - + /* reset link*/ scheduler_session_disconnect_handler(csm); - + return 0; } @@ -269,44 +269,44 @@ int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname struct CSM* csm = NULL; struct LocalInterface *lif = NULL; struct If_info * cif = NULL; - + if (!ifname) return -1; - - if(strncmp(ifname, "Po", 2)!=0) { + + if(strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX))!=0) { ICCPD_LOG_DEBUG(__FUNCTION__, "attach interface(%s) is not a port-channel", ifname); return -1; } - + csm = system_get_csm_by_mlacp_id(domain); if (csm == NULL) { ICCPD_LOG_DEBUG(__FUNCTION__, "MC-LAG ID %d doesn't exist", domain); return -1; } - + lif = local_if_find_by_name(ifname); - if (lif) + if (lif) { mlacp_bind_port_channel_to_csm(csm, ifname); } - + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) { if (strcmp(cif->name,ifname) ==0) break; } - + if(cif == NULL) { cif = (struct If_info *) malloc(sizeof(struct If_info)); if (!cif) return -1; - + snprintf(cif->name, MAX_L_PORT_NAME, "%s", ifname); LIST_INSERT_HEAD(&(csm->if_bind_list), cif, csm_next); } - + return 0; } @@ -316,17 +316,17 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) struct CSM *csm = NULL; struct LocalInterface *lif_po = NULL; struct LocalInterface *lif = NULL; - struct If_info * cif = NULL; - + struct If_info * cif = NULL; + if (!ifname) return -1; - - if (strncmp(ifname, "Po", 2)!=0) { + + if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX))!=0) { ICCPD_LOG_DEBUG(__FUNCTION__, "detach interface(%s) is not a port-channel", ifname); return -1; } - + /* find po*/ if (!(lif_po = local_if_find_by_name(ifname)) || lif_po->type != IF_T_PORT_CHANNEL @@ -335,16 +335,16 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) { return -1; } - + /* find csm*/ csm = lif_po->csm; - - ICCPD_LOG_DEBUG(__FUNCTION__, "detach mclag id = %d from ifname = %s", + + ICCPD_LOG_DEBUG(__FUNCTION__, "detach mclag id = %d from ifname = %s", csm->mlag_id, lif_po->name); - + /* process link state handler before detaching it.*/ mlacp_mlag_link_del_handler(csm, lif_po); - + unbind_poid = lif_po->po_id; mlacp_unbind_local_if(lif_po); LIST_FOREACH(lif, &(csm->app_csm.mlacp.lif_list), mlacp_next) @@ -352,11 +352,11 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) if (lif->type == IF_T_PORT && lif->po_id == unbind_poid) mlacp_unbind_local_if(lif); } - + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) { if (strcmp(ifname, cif->name) ==0) LIST_REMOVE(cif, csm_next); - } + } return 0; } diff --git a/src/iccpd/src/iccp_cmd.c b/src/iccpd/src/iccp_cmd.c index f2eeafee17bc..847b24ae956e 100644 --- a/src/iccpd/src/iccp_cmd.c +++ b/src/iccpd/src/iccp_cmd.c @@ -39,14 +39,14 @@ int set_mc_lag_by_id(uint16_t mid) struct CSM* csm = NULL; csm = system_get_csm_by_mlacp_id(mid); - if (!csm) + if (!csm) { csm = (struct CSM*)iccp_get_csm(); - if (csm == NULL) + if (csm == NULL) { return -1; } - + ret = set_mc_lag_id(csm, mid); return ret; @@ -110,8 +110,8 @@ int iccp_config_from_command(char * line) else if(strncmp(cp,"mclag_interface:",16) == 0) { cp += 10; - - while (1) + + while (1) { start = cp; while (!(*cp == ',' || *cp == '\r' || *cp == '\n') && @@ -128,7 +128,7 @@ int iccp_config_from_command(char * line) if (*cp == '\0') break; - } + } } else { diff --git a/src/iccpd/src/iccp_cmd_show.c b/src/iccpd/src/iccp_cmd_show.c index bb5119e25320..8b0e874d8662 100644 --- a/src/iccpd/src/iccp_cmd_show.c +++ b/src/iccpd/src/iccp_cmd_show.c @@ -33,14 +33,14 @@ #include "../include/iccp_cmd_show.h" #include "../include/mlacp_link_handler.h" -int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) +int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) { struct mclagd_state state_info; struct System *sys = NULL; struct CSM *csm = NULL; struct LocalInterface *peer_link_if = NULL; - struct LocalInterface *lif_po = NULL; - char unknown[] = {"UNKNOWN"}; + struct LocalInterface *lif_po = NULL; + char unknown[] = {"Unknown"}; int mclag_num= 0; int id_exist = 0; int str_size =0; @@ -89,7 +89,7 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) memcpy(state_info.peer_link_if, peer_link_if->name, ICCP_MAX_PORT_NAME); else memcpy(state_info.peer_link_if, unknown, strlen(unknown)); - + if (peer_link_if) memcpy(state_info.peer_link_mac, peer_link_if->mac_addr, 6); @@ -102,12 +102,19 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) if (str_size -len < ICCP_MAX_PORT_NAME) break; - + if (lif_po->type == IF_T_PORT_CHANNEL) - len += snprintf(state_info.enabled_po + len, str_size - len, "%s,", lif_po->name); + len += snprintf(state_info.enabled_po + len, str_size - len, "%s,", lif_po->name); } - memcpy(state_buf + MCLAGD_REPLY_INFO_HDR + mclag_num*sizeof(struct mclagd_state), + /*Skip the last ','*/ + len = strlen(state_info.enabled_po); + if(len > 0) + { + state_info.enabled_po[len-1] = '\0'; + } + + memcpy(state_buf + MCLAGD_REPLY_INFO_HDR + mclag_num*sizeof(struct mclagd_state), &state_info, sizeof(struct mclagd_state)); mclag_num ++; @@ -117,7 +124,7 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) state_buf = (char*)realloc(state_buf, state_buf_size); if (!state_buf) return EXEC_TYPE_FAILED; - } + } } *buf = state_buf; @@ -125,7 +132,7 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) if (mclag_id >0 && !id_exist) return EXEC_TYPE_NO_EXIST_MCLAGID; - + return EXEC_TYPE_SUCCESS; } @@ -150,7 +157,7 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id) arp_buf = (char*)malloc(arp_buf_size); if (!arp_buf) return EXEC_TYPE_FAILED; - + LIST_FOREACH(csm, &(sys->csm_list), next) { if (mclag_id >0) @@ -165,30 +172,30 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id) { memset(&mclagd_arp, 0, sizeof(struct mclagd_arp_msg)); iccpd_arp = (struct ARPMsg*)msg->buf; - + mclagd_arp.op_type = iccpd_arp->op_type; memcpy(mclagd_arp.ifname, iccpd_arp->ifname, strlen(iccpd_arp->ifname)); memcpy(mclagd_arp.ipv4_addr, show_ip_str(htonl(iccpd_arp->ipv4_addr)), 16); memcpy(mclagd_arp.mac_addr, iccpd_arp->mac_addr, 6); - - memcpy(arp_buf + MCLAGD_REPLY_INFO_HDR +arp_num*sizeof(struct mclagd_arp_msg), - &mclagd_arp, sizeof(struct mclagd_arp_msg)); - - arp_num ++; - + + memcpy(arp_buf + MCLAGD_REPLY_INFO_HDR +arp_num*sizeof(struct mclagd_arp_msg), + &mclagd_arp, sizeof(struct mclagd_arp_msg)); + + arp_num ++; + if ((arp_num + 1)*sizeof(struct mclagd_arp_msg) > (arp_buf_size - MCLAGD_REPLY_INFO_HDR)) { arp_buf_size += MCLAGDCTL_CMD_SIZE; arp_buf = (char*)realloc(arp_buf, arp_buf_size); if (!arp_buf) return EXEC_TYPE_FAILED; - } + } } } *buf = arp_buf; *num = arp_num; - + if (mclag_id >0 && !id_exist) return EXEC_TYPE_NO_EXIST_MCLAGID; @@ -212,11 +219,11 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id) ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); return EXEC_TYPE_NO_EXIST_SYS; } - + mac_buf = (char*)malloc(mac_buf_size); if (!mac_buf) return EXEC_TYPE_FAILED; - + LIST_FOREACH(csm, &(sys->csm_list), next) { if (mclag_id >0) @@ -239,11 +246,11 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id) memcpy(mclagd_mac.ifname, iccpd_mac->ifname, strlen(iccpd_mac->ifname)); memcpy(mclagd_mac.origin_ifname, iccpd_mac->origin_ifname, strlen(iccpd_mac->origin_ifname)); mclagd_mac.age_flag = iccpd_mac->age_flag; - - memcpy(mac_buf + MCLAGD_REPLY_INFO_HDR + mac_num*sizeof(struct mclagd_mac_msg), - &mclagd_mac, sizeof(struct mclagd_mac_msg)); - - mac_num ++; + + memcpy(mac_buf + MCLAGD_REPLY_INFO_HDR + mac_num*sizeof(struct mclagd_mac_msg), + &mclagd_mac, sizeof(struct mclagd_mac_msg)); + + mac_num ++; if ((mac_num + 1)*sizeof(struct mclagd_mac_msg) > (mac_buf_size -MCLAGD_REPLY_INFO_HDR)) { @@ -251,7 +258,7 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id) mac_buf = (char*)realloc(mac_buf, mac_buf_size); if (!mac_buf) return EXEC_TYPE_FAILED; - } + } } } @@ -288,7 +295,7 @@ int iccp_local_if_dump(char * *buf, int *num,int mclag_id) lif_buf = (char*)malloc(lif_buf_size); if (!lif_buf) return EXEC_TYPE_FAILED; - + LIST_FOREACH(csm, &(sys->csm_list), next) { if (mclag_id >0) @@ -302,33 +309,33 @@ int iccp_local_if_dump(char * *buf, int *num,int mclag_id) LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) { memset(&mclagd_lif, 0, sizeof(struct mclagd_local_if)); - + mclagd_lif.ifindex = lif_po->ifindex; - + if (lif_po->type == IF_T_UNKNOW) - memcpy(mclagd_lif.type, "UNKNOW", 6); + memcpy(mclagd_lif.type, "Unknown", 6); else if (lif_po->type == IF_T_PORT) - memcpy(mclagd_lif.type, "PORT", 4); + memcpy(mclagd_lif.type, "Ethernet", 8); else if (lif_po->type == IF_T_PORT_CHANNEL) - memcpy(mclagd_lif.type, "PORT-CHANNEL", 12); + memcpy(mclagd_lif.type, "PortChannel", 11); memcpy(mclagd_lif.name, lif_po->name, MAX_L_PORT_NAME); memcpy(mclagd_lif.mac_addr, lif_po->mac_addr, ETHER_ADDR_LEN); if (lif_po->state == PORT_STATE_UP) - memcpy(mclagd_lif.state, "UP", 2); + memcpy(mclagd_lif.state, "Up", 2); else if (lif_po->state == PORT_STATE_DOWN) - memcpy(mclagd_lif.state, "DOWN", 4); + memcpy(mclagd_lif.state, "Down", 4); else if (lif_po->state == PORT_STATE_ADMIN_DOWN) - memcpy(mclagd_lif.state, "ADMIN-DOWN", 10); + memcpy(mclagd_lif.state, "Admin-down", 10); else if (lif_po->state == PORT_STATE_TEST) - memcpy(mclagd_lif.state, "TEST", 4); + memcpy(mclagd_lif.state, "Test", 4); memcpy(mclagd_lif.ipv4_addr, show_ip_str(htonl(lif_po->ipv4_addr)), 16); mclagd_lif.prefixlen = lif_po->prefixlen; mclagd_lif.l3_mode = local_if_is_l3_mode(lif_po); - + mclagd_lif.is_peer_link = lif_po->is_peer_link; memcpy(mclagd_lif.portchannel_member_buf, lif_po->portchannel_member_buf, 512); @@ -350,21 +357,21 @@ int iccp_local_if_dump(char * *buf, int *num,int mclag_id) mclagd_lif.isolate_to_peer_link = lif_po->isolate_to_peer_link; str_buf = mclagd_lif.vlanlist; - + len = 0; LIST_FOREACH(vlan_id, &(lif_po->vlan_list), port_next) { - if (vlan_id != NULL ) + if (vlan_id != NULL ) { if (str_size -len < 4) break; - len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid); + len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid); } } - - memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num*sizeof(struct mclagd_local_if), - &mclagd_lif, sizeof(struct mclagd_local_if)); - + + memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num*sizeof(struct mclagd_local_if), + &mclagd_lif, sizeof(struct mclagd_local_if)); + lif_num ++; if ((lif_num + 1)*sizeof(struct mclagd_local_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR)) @@ -373,13 +380,13 @@ int iccp_local_if_dump(char * *buf, int *num,int mclag_id) lif_buf = (char*)realloc(lif_buf, lif_buf_size); if (!lif_buf) return EXEC_TYPE_FAILED; - } + } } } *buf = lif_buf; *num = lif_num; - + if (mclag_id >0 && !id_exist) return EXEC_TYPE_NO_EXIST_MCLAGID; @@ -406,7 +413,7 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) pif_buf = (char*)malloc(pif_buf_size); if (!pif_buf) return EXEC_TYPE_FAILED; - + LIST_FOREACH(csm, &(sys->csm_list), next) { if (mclag_id >0) @@ -420,35 +427,35 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) LIST_FOREACH(pif_po, &(MLACP(csm).pif_list), mlacp_next) { memset(&mclagd_pif, 0, sizeof(struct mclagd_peer_if)); - + mclagd_pif.ifindex = pif_po->ifindex; - + if (pif_po->type == IF_T_UNKNOW) - memcpy(mclagd_pif.type, "UNKNOW", 6); + memcpy(mclagd_pif.type, "Unknown", 6); else if (pif_po->type == IF_T_PORT) - memcpy(mclagd_pif.type, "PORT", 4); + memcpy(mclagd_pif.type, "Ethernet", 8); else if (pif_po->type == IF_T_PORT_CHANNEL) - memcpy(mclagd_pif.type, "PORT-CHANNEL", 12); + memcpy(mclagd_pif.type, "PortChannel", 11); memcpy(mclagd_pif.name, pif_po->name, MAX_L_PORT_NAME); memcpy(mclagd_pif.mac_addr, pif_po->mac_addr, ETHER_ADDR_LEN); if (pif_po->state == PORT_STATE_UP) - memcpy(mclagd_pif.state, "UP", 2); + memcpy(mclagd_pif.state, "Up", 2); else if (pif_po->state == PORT_STATE_DOWN) - memcpy(mclagd_pif.state, "DOWN", 4); + memcpy(mclagd_pif.state, "Down", 4); else if (pif_po->state == PORT_STATE_ADMIN_DOWN) - memcpy(mclagd_pif.state, "ADMIN-DOWN", 10); + memcpy(mclagd_pif.state, "Admin-down", 10); else if (pif_po->state == PORT_STATE_TEST) - memcpy(mclagd_pif.state, "TEST", 4); + memcpy(mclagd_pif.state, "Test", 4); mclagd_pif.po_id = pif_po->po_id; mclagd_pif.po_active = pif_po->po_active; - memcpy(pif_buf + MCLAGD_REPLY_INFO_HDR + pif_num*sizeof(struct mclagd_peer_if), - &mclagd_pif, sizeof(struct mclagd_peer_if)); - - pif_num ++; + memcpy(pif_buf + MCLAGD_REPLY_INFO_HDR + pif_num*sizeof(struct mclagd_peer_if), + &mclagd_pif, sizeof(struct mclagd_peer_if)); + + pif_num ++; if ((pif_num + 1)*sizeof(struct mclagd_peer_if) > (pif_buf_size - MCLAGD_REPLY_INFO_HDR)) { @@ -457,12 +464,12 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) if (!pif_buf) return EXEC_TYPE_FAILED; } - } + } } - + *buf = pif_buf; *num = pif_num; - + if (mclag_id >0 && !id_exist) return EXEC_TYPE_NO_EXIST_MCLAGID; diff --git a/src/iccpd/src/iccp_consistency_check.c b/src/iccpd/src/iccp_consistency_check.c index da5076b4b10d..39302a23be10 100644 --- a/src/iccpd/src/iccp_consistency_check.c +++ b/src/iccpd/src/iccp_consistency_check.c @@ -48,19 +48,19 @@ static int iccp_check_interface_mode( char* ifname) { struct CSM* csm = NULL; struct LocalInterface* local_if = NULL; - struct PeerInterface* peer_if = NULL; - + struct PeerInterface* peer_if = NULL; + local_if = local_if_find_by_name(ifname); if(local_if == NULL) - return -2; + return -2; csm = local_if->csm; if(csm == NULL) return -3; - + peer_if = peer_if_find_by_name(csm, ifname); if(peer_if == NULL) - return -4; + return -4; if(peer_if->l3_mode != local_if->l3_mode) return -5; @@ -71,12 +71,12 @@ static int iccp_check_interface_mode( char* ifname) static int iccp_check_interface_layer3_addr(char* ifname) { struct CSM* csm = NULL; - struct LocalInterface* local_if = NULL; + struct LocalInterface* local_if = NULL; struct PeerInterface* peer_if = NULL; - + local_if = local_if_find_by_name(ifname); if(local_if == NULL) - return -2; + return -2; csm = local_if->csm; if(csm == NULL) @@ -84,7 +84,7 @@ static int iccp_check_interface_layer3_addr(char* ifname) peer_if = peer_if_find_by_name(csm, ifname); if(peer_if == NULL) - return -4; + return -4; if(peer_if->ipv4_addr != local_if->ipv4_addr) return -5; @@ -102,7 +102,7 @@ static int iccp_check_interface_vlan(char* ifname) local_if = local_if_find_by_name(ifname); if(local_if == NULL) - return -2; + return -2; csm = local_if->csm; if(csm == NULL) @@ -110,7 +110,7 @@ static int iccp_check_interface_vlan(char* ifname) peer_if = peer_if_find_by_name(csm, ifname); if(peer_if == NULL) - return -4; + return -4; LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next) { diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c index 80556fa7fe98..b22822945a26 100644 --- a/src/iccpd/src/iccp_csm.c +++ b/src/iccpd/src/iccp_csm.c @@ -23,7 +23,7 @@ #include #include - + #include "../include/logger.h" #include "../include/system.h" #include "../include/scheduler.h" @@ -55,36 +55,36 @@ char g_csm_buf[CSM_BUFFER_SIZE]={0}; uint32_t ICCP_MSG_ID = 0x1; /* Enter Connection State Machine NONEXISTENT handle function */ -static void iccp_csm_enter_state_nonexistent(struct CSM* csm) +static void iccp_csm_enter_state_nonexistent(struct CSM* csm) { iccp_csm_finalize(csm); } /* Enter Connection State Machine INITIALIZED handle function */ -static void iccp_csm_enter_state_initialized(struct CSM* csm) +static void iccp_csm_enter_state_initialized(struct CSM* csm) { if (csm == NULL) return; - + csm->iccp_info.sender_capability_flag = 0x1; } /* Enter Connection State Machine CAPREC handle function */ -static void iccp_csm_enter_state_caprec(struct CSM* csm) +static void iccp_csm_enter_state_caprec(struct CSM* csm) { if (csm == NULL) return; - + csm->iccp_info.sender_capability_flag = 0x1; csm->iccp_info.peer_capability_flag = 0x1; } /* Enter Connection State Machine CONNECTING handle function */ -static void iccp_csm_enter_state_connecting(struct CSM* csm) +static void iccp_csm_enter_state_connecting(struct CSM* csm) { if (csm == NULL) return; - + csm->iccp_info.sender_rg_connect_flag = 0x1; } @@ -92,7 +92,7 @@ static void iccp_csm_enter_state_connecting(struct CSM* csm) static void iccp_csm_enter_state_operational(struct CSM* csm) { if (csm == NULL) return; - + csm->iccp_info.sender_rg_connect_flag = 0x1; csm->iccp_info.peer_rg_connect_flag = 0x1; } @@ -101,13 +101,13 @@ void *iccp_get_csm() { struct CSM* csm = NULL; struct System* sys = NULL; - + if((sys = system_get_instance()) == NULL) { return NULL; } - + csm = system_create_csm(); - + return csm; } @@ -123,20 +123,21 @@ void iccp_csm_init(struct CSM* csm) /* Connection State Machine instance status reset */ void iccp_csm_status_reset(struct CSM* csm, int all) -{ +{ ICCP_CSM_QUEUE_REINIT(csm->msg_list); - + if(all) { bzero(csm, sizeof(struct CSM)); ICCP_CSM_QUEUE_REINIT(csm->msg_list); } - + csm->sock_fd = -1; pthread_mutex_init(&csm->conn_mutex, NULL); csm->connTimePrev = 0; csm->heartbeat_send_time = 0; csm->heartbeat_update_time = 0; + csm->peer_warm_reboot_time = 0; /*csm->sysid_update_time = 0;*/ csm->isolate_update_time = 0; csm->role_type = STP_ROLE_NONE; @@ -154,31 +155,43 @@ void iccp_csm_status_reset(struct CSM* csm, int all) csm->iccp_info.sender_capability_flag = 0x0; csm->iccp_info.sender_rg_connect_flag = 0x0; app_csm_init(csm, all); - + memset(&csm->msg_log, 0, sizeof(struct MsgLog)); } /* Connection State Machine instance tear down */ void iccp_csm_finalize(struct CSM* csm) { - struct If_info * cif = NULL; + struct If_info * cif = NULL; + struct System* sys = NULL; + if (csm == NULL) return; - /* Clean all port block*/ - peerlink_port_isolate_cleanup(csm); - + if((sys = system_get_instance()) == NULL) + return; + + /*If warm reboot, don't change port block and peer link MAC learning*/ + if(sys->warmboot_exit != WARM_REBOOT) + { + /* Clean all port block*/ + peerlink_port_isolate_cleanup(csm); + + /*Enable peer link port MAC learning*/ + set_peerlink_mlag_port_learn(csm->peer_link_if, 1); + } + /* Disconnect from peer */ scheduler_session_disconnect_handler(csm); - + /* Release all Connection State Machine instance */ app_csm_finalize(csm); - + LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) { LIST_REMOVE(cif, csm_next); - } - + } + /* Release iccp_csm */ pthread_mutex_destroy(&(csm->conn_mutex)); iccp_csm_msg_list_finalize(csm); @@ -203,19 +216,19 @@ void iccp_csm_msg_list_finalize(struct CSM* csm) } /* Send message to peer */ -int iccp_csm_send(struct CSM* csm, char* buf, int msg_len) +int iccp_csm_send(struct CSM* csm, char* buf, int msg_len) { LDPHdr* ldp_hdr = (LDPHdr*) buf; ICCParameter* param = NULL; - + if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0) return -1; - + if(ntohs(ldp_hdr->msg_type) == MSG_T_CAPABILITY) param = (struct ICCParameter*)&buf[sizeof(LDPHdr)]; else param = (struct ICCParameter*)&buf[sizeof(ICCHdr)]; - + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Send(%d): len=[%d] msg_type=[%s (0x%X, 0x%X)]", csm->sock_fd, msg_len, get_tlv_type_string(param->type), ldp_hdr->msg_type, param->type);*/ csm->msg_log.msg[csm->msg_log.end_index].msg_id = ntohl(ldp_hdr->msg_id); csm->msg_log.msg[csm->msg_log.end_index].type = ntohs(ldp_hdr->msg_type); @@ -223,22 +236,22 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len) ++csm->msg_log.end_index; if(csm->msg_log.end_index >= 128) csm->msg_log.end_index = 0; - + return write(csm->sock_fd, buf, msg_len); } /* Connection State Machine Transition */ -void iccp_csm_transit(struct CSM* csm) +void iccp_csm_transit(struct CSM* csm) { int len = -1; struct Msg* msg = NULL; ICCP_CONNECTION_STATE_E prev_state; - + if (!csm) return; - + prev_state = csm->current_state; - + /* No connection, but have state change? reset it...*/ if (csm->current_state != ICCP_NONEXISTENT && csm->sock_fd <= 0) { @@ -246,12 +259,12 @@ void iccp_csm_transit(struct CSM* csm) iccp_csm_enter_state_nonexistent(csm); return; } - + /*if (csm->current_state != ICCP_NONEXISTENT) ICCPD_LOG_DEBUG(__FUNCTION__, "#Begin# id:%d, fd:%d, ICCP CSM State:%d", csm->mlag_id, csm->sock_fd, csm->current_state);*/ - + msg = iccp_csm_dequeue_msg(csm); - + switch (csm->current_state) { case ICCP_NONEXISTENT: @@ -310,12 +323,12 @@ void iccp_csm_transit(struct CSM* csm) default: break; } - - if (prev_state != csm->current_state || (csm->current_state && msg != NULL)) + + if (prev_state != csm->current_state || (csm->current_state && msg != NULL)) { - ICCPD_LOG_INFO(__FUNCTION__, "csm %d enter state %d .", csm->mlag_id, csm->current_state); - - switch (csm->current_state) + ICCPD_LOG_INFO(__FUNCTION__, "csm %d enter state %d .", csm->mlag_id, csm->current_state); + + switch (csm->current_state) { case ICCP_NONEXISTENT: iccp_csm_enter_state_nonexistent(csm); @@ -344,14 +357,14 @@ void iccp_csm_transit(struct CSM* csm) } /* Set up ICCP message */ -int iccp_csm_prepare_iccp_msg(struct CSM* csm, char* buf, size_t max_buf_size) +int iccp_csm_prepare_iccp_msg(struct CSM* csm, char* buf, size_t max_buf_size) { size_t msg_len = -1; - + if (csm == NULL || buf == NULL) return -1; - - switch (csm->current_state) + + switch (csm->current_state) { case ICCP_NONEXISTENT: /* Do nothing on this state */ @@ -382,75 +395,75 @@ int iccp_csm_prepare_iccp_msg(struct CSM* csm, char* buf, size_t max_buf_size) } break; } - + return msg_len; } /* ICCP capability message handle function */ -int iccp_csm_prepare_capability_msg(struct CSM* csm, char* buf, size_t max_buf_size) +int iccp_csm_prepare_capability_msg(struct CSM* csm, char* buf, size_t max_buf_size) { LDPHdr* ldp_hdr = (LDPHdr*) buf; LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*) &buf[sizeof(LDPHdr)]; size_t msg_len = sizeof(LDPHdr) + sizeof(LDPICCPCapabilityTLV); memset(buf, 0, max_buf_size); - + /* LDP header */ ldp_hdr->u_bit = 0x0; ldp_hdr->msg_type = htons(MSG_T_CAPABILITY); ldp_hdr->msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); ldp_hdr->msg_id = htonl(ICCP_MSG_ID++); - + /* LDP ICCP capability TLV */ cap->icc_parameter.u_bit = 0x1; cap->icc_parameter.f_bit = 0x0; cap->icc_parameter.type = TLV_T_ICCP_CAPABILITY; - *(uint16_t *)cap = htons(*(uint16_t *)cap); + *(uint16_t *)cap = htons(*(uint16_t *)cap); cap->icc_parameter.len = htons(TLV_L_ICCP_CAPABILITY); - cap->s_bit = csm->iccp_info.sender_capability_flag; + cap->s_bit = csm->iccp_info.sender_capability_flag; *(uint16_t *)((uint8_t *)cap+sizeof(ICCParameter)) = htons(*(uint16_t *)((uint8_t *)cap+sizeof(ICCParameter))); cap->major_ver = 0x1; cap->minior_ver = 0x0; - + return msg_len; } -void iccp_csm_fill_icc_rg_id_tlv(struct CSM* csm, ICCHdr* icc_hdr) +void iccp_csm_fill_icc_rg_id_tlv(struct CSM* csm, ICCHdr* icc_hdr) { if (!csm || !icc_hdr) return; - + icc_hdr->icc_rg_id_tlv.type = htons(TLV_T_ICC_RG_ID); icc_hdr->icc_rg_id_tlv.len = htons(TLV_L_ICC_RG_ID); icc_hdr->icc_rg_id_tlv.icc_rg_id = htonl(csm->iccp_info.icc_rg_id); } /* ICCP NAK message handle function */ -int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) +int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) { ICCHdr* icc_hdr = (ICCHdr*) buf; NAKTLV* nak = (NAKTLV*) &buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); - + memset(buf, 0, max_buf_size); - + /* ICC header */ icc_hdr->ldp_hdr.u_bit = 0x0; - icc_hdr->ldp_hdr.msg_type = htons(MSG_T_NOTIFICATION); + icc_hdr->ldp_hdr.msg_type = htons(MSG_T_NOTIFICATION); icc_hdr->ldp_hdr.msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); icc_hdr->ldp_hdr.msg_id = htonl(ICCP_MSG_ID++); iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); - + /* NAL TLV */ nak->icc_parameter.u_bit = 0x0; nak->icc_parameter.f_bit = 0x0; - nak->icc_parameter.type = htons(TLV_T_NAK); - nak->icc_parameter.len = htons(sizeof(((struct NAKTLV*) 0)->iccp_status_code) + sizeof(((struct NAKTLV*) 0)->rejected_msg_id)); - - switch (csm->iccp_info.status_code) + nak->icc_parameter.type = htons(TLV_T_NAK); + nak->icc_parameter.len = htons(sizeof(((struct NAKTLV*) 0)->iccp_status_code) + sizeof(((struct NAKTLV*) 0)->rejected_msg_id)); + + switch (csm->iccp_info.status_code) { case STATUS_CODE_U_ICCP_RG: nak->iccp_status_code = htonl(csm->iccp_info.status_code); @@ -467,86 +480,86 @@ int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) case STATUS_CODE_ICCP_APP_REMOVED_FROM_RG: break; } - + return msg_len; } /* ICCP RG connect handle function */ -int iccp_csm_prepare_rg_connect_msg(struct CSM* csm, char* buf, size_t max_buf_size) +int iccp_csm_prepare_rg_connect_msg(struct CSM* csm, char* buf, size_t max_buf_size) { ICCHdr* icc_hdr = (ICCHdr*) buf; ICCSenderNameTLV* sender = (ICCSenderNameTLV*) &buf[sizeof(ICCHdr)]; size_t name_len = strlen(csm->iccp_info.sender_name); size_t msg_len = sizeof(ICCHdr) + sizeof(ICCParameter) + name_len; - + memset(buf, 0, max_buf_size); - + /* ICC header */ icc_hdr->ldp_hdr.u_bit = 0x0; icc_hdr->ldp_hdr.msg_type = htons(MSG_T_RG_CONNECT); icc_hdr->ldp_hdr.msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); icc_hdr->ldp_hdr.msg_id = htonl(ICCP_MSG_ID++); iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); - + /* ICC sender name TLV */ sender->icc_parameter.u_bit = 0x0; sender->icc_parameter.f_bit = 0x0; - sender->icc_parameter.type = htons(TLV_T_ICC_SENDER_NAME); + sender->icc_parameter.type = htons(TLV_T_ICC_SENDER_NAME); sender->icc_parameter.len = htons(name_len); memcpy(sender->sender_name, csm->iccp_info.sender_name, name_len); - + return msg_len; } /* ICCP RG disconnect handle function */ -int iccp_csm_prepare_rg_disconnect_msg(struct CSM* csm, char* buf, size_t max_buf_size) +int iccp_csm_prepare_rg_disconnect_msg(struct CSM* csm, char* buf, size_t max_buf_size) { ICCHdr* icc_hdr = (ICCHdr*) buf; DisconnectCodeTLV* disconn_code = (DisconnectCodeTLV*) &buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(DisconnectCodeTLV); - + memset(buf, 0, max_buf_size); - + /* ICC header */ icc_hdr->ldp_hdr.u_bit = 0x0; - icc_hdr->ldp_hdr.msg_type = htons(MSG_T_RG_DISCONNECT); + icc_hdr->ldp_hdr.msg_type = htons(MSG_T_RG_DISCONNECT); icc_hdr->ldp_hdr.msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); icc_hdr->ldp_hdr.msg_id = htonl(ICCP_MSG_ID++); iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); - + /* Disconnect code TLV */ disconn_code->icc_parameter.u_bit = 0x0; disconn_code->icc_parameter.f_bit = 0x0; - disconn_code->icc_parameter.type = htons(TLV_T_DISCONNECT_CODE); + disconn_code->icc_parameter.type = htons(TLV_T_DISCONNECT_CODE); disconn_code->icc_parameter.len = htons(sizeof(((struct DisconnectCodeTLV*) 0)->iccp_status_code)); disconn_code->iccp_status_code = htonl(csm->iccp_info.status_code); - + return msg_len; } /* Check ID(MC-LAG ID, mLACP ID, RG ID) from received message */ -static void iccp_csm_check_id_from_msg(struct CSM* csm, struct Msg* msg) +static void iccp_csm_check_id_from_msg(struct CSM* csm, struct Msg* msg) { ICCHdr* icc_hdr = NULL; - + if (!csm || !msg || !msg->buf) return; - + icc_hdr = (ICCHdr*) msg->buf; - + /* Capability Message doesn't have ICC RG ID TLV */ if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) return; - + /* Check if received message ID same as local configuration */ - if (ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id) == csm->iccp_info.icc_rg_id) + if (ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id) == csm->iccp_info.icc_rg_id) { - if (csm->iccp_info.status_code == STATUS_CODE_U_ICCP_RG) + if (csm->iccp_info.status_code == STATUS_CODE_U_ICCP_RG) { csm->iccp_info.status_code = 0x0; csm->iccp_info.rejected_msg_id = 0x0; } - } else if (ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id) != csm->iccp_info.icc_rg_id) + } else if (ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id) != csm->iccp_info.icc_rg_id) { csm->iccp_info.status_code = STATUS_CODE_U_ICCP_RG; csm->iccp_info.rejected_msg_id = ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id); @@ -554,47 +567,47 @@ static void iccp_csm_check_id_from_msg(struct CSM* csm, struct Msg* msg) } /* Receive message correspond function */ -void iccp_csm_correspond_from_msg(struct CSM* csm, struct Msg* msg) +void iccp_csm_correspond_from_msg(struct CSM* csm, struct Msg* msg) { ICCHdr* icc_hdr = NULL; - + if (csm == NULL || msg == NULL || msg->buf == NULL) return; - + icc_hdr = (ICCHdr*) msg->buf; - NAKTLV* nak = (NAKTLV*)( icc_hdr+sizeof(ICCHdr)); + NAKTLV* nak = (NAKTLV*)( icc_hdr+sizeof(ICCHdr)); iccp_csm_check_id_from_msg(csm, msg); - + if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) iccp_csm_correspond_from_capability_msg(csm, msg); else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_CONNECT) iccp_csm_correspond_from_rg_connect_msg(csm, msg); else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_DISCONNECT) iccp_csm_correspond_from_rg_disconnect_msg(csm, msg); - else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) { ICCPD_LOG_DEBUG(__FUNCTION__, "Received MSG_T_NOTIFICATION ,err status %s reason of %s", get_status_string(ntohl(nak->iccp_status_code)), get_status_string(csm->iccp_info.status_code)); - sleep(1); - } - else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + sleep(1); + } + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) { ;// do nothing - } + } else { ++csm->u_msg_in_count; } - + free(msg->buf); free(msg); } /* Receive capability message correspond function */ -void iccp_csm_correspond_from_capability_msg(struct CSM* csm, struct Msg* msg) +void iccp_csm_correspond_from_capability_msg(struct CSM* csm, struct Msg* msg) { LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*) &(msg->buf)[sizeof(LDPHdr)]; - *(uint16_t *)cap = ntohs(*(uint16_t *)cap); + *(uint16_t *)cap = ntohs(*(uint16_t *)cap); *(uint16_t *)((uint8_t *)cap+sizeof(ICCParameter)) = ntohs(*(uint16_t *)((uint8_t *)cap+sizeof(ICCParameter))); if (cap->icc_parameter.u_bit == 0x1 @@ -610,12 +623,12 @@ void iccp_csm_correspond_from_capability_msg(struct CSM* csm, struct Msg* msg) } /* Receive RG connect message correspond function */ -void iccp_csm_correspond_from_rg_connect_msg(struct CSM* csm, struct Msg* msg) +void iccp_csm_correspond_from_rg_connect_msg(struct CSM* csm, struct Msg* msg) { ICCSenderNameTLV* sender = (ICCSenderNameTLV*) &(msg->buf)[sizeof(ICCHdr)]; - *(uint16_t *)sender = ntohs(*(uint16_t *)sender); - + *(uint16_t *)sender = ntohs(*(uint16_t *)sender); + if (sender->icc_parameter.u_bit == 0x0 && sender->icc_parameter.f_bit == 0x0 && sender->icc_parameter.type == TLV_T_ICC_SENDER_NAME) @@ -625,12 +638,12 @@ void iccp_csm_correspond_from_rg_connect_msg(struct CSM* csm, struct Msg* msg) } /* Receive RG disconnect message correspond function */ -void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM* csm, struct Msg* msg) +void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM* csm, struct Msg* msg) { DisconnectCodeTLV* diconn_code = (DisconnectCodeTLV*) &(msg->buf)[sizeof(ICCHdr)]; - *(uint16_t *)diconn_code = ntohs(*(uint16_t *)diconn_code); - + *(uint16_t *)diconn_code = ntohs(*(uint16_t *)diconn_code); + if (diconn_code->icc_parameter.u_bit == 0x0 && diconn_code->icc_parameter.f_bit == 0x0 && diconn_code->icc_parameter.type == TLV_T_DISCONNECT_CODE @@ -643,66 +656,66 @@ void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM* csm, struct Msg* msg } /* Add received message into message list */ -void iccp_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) +void iccp_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) { ICCHdr* icc_hdr = NULL; NAKTLV* naktlv = NULL; int type = -1; int i = 0; - + if (csm == NULL) { if (msg != NULL) free(msg); return; } - + if (msg == NULL) return; - + icc_hdr = (ICCHdr*) msg->buf; - *(uint16_t *)icc_hdr = ntohs(*(uint16_t *)icc_hdr); + *(uint16_t *)icc_hdr = ntohs(*(uint16_t *)icc_hdr); - if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) { app_csm_enqueue_msg(csm, msg); } - else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) + else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) { naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; - + for(i=0; irejected_msg_id) == csm->msg_log.msg[i].msg_id) + if(ntohl(naktlv->rejected_msg_id) == csm->msg_log.msg[i].msg_id) { type = csm->msg_log.msg[i].type; break; } } - + if(type == MSG_T_RG_APP_DATA) app_csm_enqueue_msg(csm, msg); else TAILQ_INSERT_TAIL(&(csm->msg_list), msg, tail); } - else + else { TAILQ_INSERT_TAIL(&(csm->msg_list), msg, tail); } } /* Get received message from message list */ -struct Msg* iccp_csm_dequeue_msg(struct CSM* csm) +struct Msg* iccp_csm_dequeue_msg(struct CSM* csm) { struct Msg* msg = NULL; - if (!TAILQ_EMPTY(&(csm->msg_list))) + if (!TAILQ_EMPTY(&(csm->msg_list))) { msg = TAILQ_FIRST(&(csm->msg_list)); TAILQ_REMOVE(&(csm->msg_list), msg, tail); - + } - + return msg; } @@ -710,34 +723,34 @@ struct Msg* iccp_csm_dequeue_msg(struct CSM* csm) int iccp_csm_init_msg(struct Msg** msg, char* data, int len) { struct Msg* iccp_msg = NULL; - + if (msg == NULL) return -2; - + if(data == NULL || len <= 0) return -1; - + iccp_msg = (struct Msg*) malloc(sizeof(struct Msg)); if (iccp_msg == NULL) goto err_ret; - + iccp_msg->buf = (char*) malloc(len); if (iccp_msg->buf == NULL) goto err_ret; - + memcpy(iccp_msg->buf, data, len); iccp_msg->len = len; *msg = iccp_msg; - + return 0; - + err_ret: if(iccp_msg) { if(iccp_msg->buf) free(iccp_msg->buf); free(iccp_msg); } - + return -1; } diff --git a/src/iccpd/src/iccp_ifm.c b/src/iccpd/src/iccp_ifm.c index 03d4d7421147..8dd3f61f9225 100644 --- a/src/iccpd/src/iccp_ifm.c +++ b/src/iccpd/src/iccp_ifm.c @@ -50,10 +50,10 @@ static int iccp_valid_handler(struct nl_msg *msg, void *arg) unsigned int event = 0; if (nlh->nlmsg_type != RTM_NEWLINK) return 0; - + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) ICCPD_LOG_ERR(__FUNCTION__, "Unknown message type."); - + return 0; } @@ -68,35 +68,35 @@ int iccp_sys_local_if_list_get_init() }; int ret; int retry = 1; - + if (!(sys = system_get_instance())) return -1; - - while (retry) + + while (retry) { retry = 0; ret = nl_send_simple(sys->route_sock, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr)); - if (ret < 0) + if (ret < 0) { ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); return ret; } - + orig_cb = nl_socket_get_cb(sys->route_sock); cb = nl_cb_clone(orig_cb); nl_cb_put(orig_cb); - if (!cb) + if (!cb) { ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); return -ENOMEM; } - + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_valid_handler, sys); - + ret = nl_recvmsgs(sys->route_sock, cb); nl_cb_put(cb); - if (ret < 0) + if (ret < 0) { ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error. ret = %d errno = %d ",ret, errno); if (ret != -NLE_DUMP_INTR) @@ -104,7 +104,7 @@ int iccp_sys_local_if_list_get_init() retry = 1; } } - + return ret; } @@ -116,22 +116,22 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) struct ARPMsg *arp_msg = NULL, *arp_info = NULL; struct VLAN_ID *vlan_id_list = NULL; struct Msg *msg_send = NULL; - + char buf[MAX_BUFSIZE]; size_t msg_len = 0; - + struct LocalInterface *lif_po = NULL, *arp_lif = NULL; - + int verify_arp = 0; int arp_update = 0; - + if (!(sys = system_get_instance())) return; - + /* Find local itf*/ if (!(arp_lif = local_if_find_by_ifindex(ndm->ndm_ifindex))) return; - + /* create ARP msg*/ memset(buf, 0, MAX_BUFSIZE); msg_len = sizeof(struct ARPMsg); @@ -143,13 +143,13 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) if (tb[NDA_LLADDR]) memcpy(arp_msg->mac_addr, RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR])); - arp_msg->ipv4_addr = ntohl(arp_msg->ipv4_addr); + arp_msg->ipv4_addr = ntohl(arp_msg->ipv4_addr); ICCPD_LOG_DEBUG(__FUNCTION__, "arp msg type %d , state (%04X)(%d) ifindex [%d] (%s) ip %s , mac [%02X:%02X:%02X:%02X:%02X:%02X] ", msgtype, ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), ndm->ndm_ifindex, arp_lif->name, show_ip_str(htonl(arp_msg->ipv4_addr)), - arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3],arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3],arp_msg->mac_addr[4],arp_msg->mac_addr[5]); /*Debug*/ #if 1 @@ -164,7 +164,7 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) arp_msg->mac_addr[4],arp_msg->mac_addr[5]); fprintf(stderr, "==============================\n"); #endif - + /* Find MLACP itf, member of port-channel*/ LIST_FOREACH(csm, &(sys->csm_list), next) { @@ -172,8 +172,8 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) { if (lif_po->type != IF_T_PORT_CHANNEL) continue; - - if (!local_if_is_l3_mode(lif_po)) + + if (!local_if_is_l3_mode(lif_po)) { /* Is the L2 MLAG itf belong to a vlan?*/ LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) @@ -183,40 +183,40 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) continue; break; } - + if (!vlan_id_list) continue; - - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", + + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", lif_po->name, vlan_id_list->vlan_itf->name); } - else + else { /* Is the ARP belong to a L3 mode MLAG itf?*/ if (ndm->ndm_ifindex != lif_po->ifindex) continue; - + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", lif_po->name); } - + verify_arp = 1; - + break; } - + if (lif_po) break; } - + if (!(csm && lif_po)) return; if (!verify_arp) return; - + /* update lif ARP*/ TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { arp_info = (struct ARPMsg*) msg->buf; if (arp_info->ipv4_addr != arp_msg->ipv4_addr) continue; - - if (msgtype == RTM_DELNEIGH) + + if (msgtype == RTM_DELNEIGH) { /* delete ARP*/ TAILQ_REMOVE(&MLACP(csm).arp_list, msg, tail); @@ -224,7 +224,7 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) ICCPD_LOG_DEBUG(__FUNCTION__, "Delete ARP %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } - else + else { /* update ARP*/ if(arp_info->op_type != arp_msg->op_type @@ -243,52 +243,52 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) } break; } - + if (msg && !arp_update) return; - - if (msgtype != RTM_DELNEIGH) + + if (msgtype != RTM_DELNEIGH) { /* enquene lif_msg (add)*/ - if (!msg) + if (!msg) { arp_msg->op_type = ARP_SYNC_LIF; - if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) { mlacp_enqueue_arp(csm, msg); - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr))); } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr))); } - + /* enqueue iccp_msg (add)*/ - if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { arp_msg->op_type = ARP_SYNC_ADD; - if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } - else + else ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); - + } } - else + else { /* enqueue iccp_msg (delete)*/ - if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { arp_msg->op_type = ARP_SYNC_DEL; - if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[DEL] for %s", @@ -297,10 +297,10 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) else ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[DEL] for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); - + } } - + /*Debug: dump for dequeue ARP Info*/ #if 1 fprintf(stderr, "\n======== ARP Info List ========\n"); @@ -311,7 +311,7 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) } fprintf(stderr, "==============================\n"); #endif - + /*TEST dump for dequeue ARP message*/ #if 0 while (MLACP(csm).arp_updated && !TAILQ_EMPTY(&(MLACP(csm).arp_msg_list))) @@ -333,7 +333,7 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) } MLACP(csm).arp_updated = 0; #endif - + return; } @@ -353,7 +353,7 @@ int do_one_neigh_request (struct nlmsghdr *n) int len = n->nlmsg_len; struct rtattr * tb[NDA_MAX+1]; - if (n->nlmsg_type == NLMSG_DONE) + if (n->nlmsg_type == NLMSG_DONE) { return 0; } @@ -377,16 +377,16 @@ int do_one_neigh_request (struct nlmsghdr *n) return(0); } - if (!tb[NDA_DST] || ndm->ndm_type != RTN_UNICAST) + if (!tb[NDA_DST] || ndm->ndm_type != RTN_UNICAST) { return(0); } - if (ndm->ndm_family == AF_INET) + if (ndm->ndm_family == AF_INET) { - do_arp_request(ndm, tb, n->nlmsg_type); + do_arp_request(ndm, tb, n->nlmsg_type); } - + return(0); } @@ -394,9 +394,9 @@ int do_one_neigh_request (struct nlmsghdr *n) static int iccp_arp_valid_handler(struct nl_msg *msg, void *arg) { struct nlmsghdr *nlh = nlmsg_hdr(msg); - + do_one_neigh_request(nlh); - + return 0; } @@ -415,12 +415,12 @@ int iccp_arp_get_init() if (!(sys = system_get_instance())) return -1; - while (retry) + while (retry) { retry = 0; ret = nl_send_simple(sys->route_sock, RTM_GETNEIGH, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr)); - if (ret < 0) + if (ret < 0) { ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); return ret; @@ -429,7 +429,7 @@ int iccp_arp_get_init() orig_cb = nl_socket_get_cb(sys->route_sock); cb = nl_cb_clone(orig_cb); nl_cb_put(orig_cb); - if (!cb) + if (!cb) { ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); return -ENOMEM; @@ -439,7 +439,7 @@ int iccp_arp_get_init() ret = nl_recvmsgs(sys->route_sock, cb); nl_cb_put(cb); - if (ret < 0) + if (ret < 0) { ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error."); if (ret != -NLE_DUMP_INTR) @@ -461,21 +461,21 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET struct ARPMsg *arp_msg = NULL, *arp_info = NULL; struct VLAN_ID *vlan_id_list = NULL; struct Msg *msg_send = NULL; - + char buf[MAX_BUFSIZE]; size_t msg_len = 0; - + struct LocalInterface *lif_po = NULL, *arp_lif = NULL; - + int verify_arp = 0; - + if (!(sys = system_get_instance())) return; - + /* Find local itf*/ if (!(arp_lif = local_if_find_by_ifindex(ifindex))) return; - + /* create ARP msg*/ memset(buf, 0, MAX_BUFSIZE); msg_len = sizeof(struct ARPMsg); @@ -497,7 +497,7 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET arp_msg->mac_addr[4],arp_msg->mac_addr[5]); fprintf(stderr, "==============================\n"); #endif - + /* Find MLACP itf, member of port-channel*/ LIST_FOREACH(csm, &(sys->csm_list), next) { @@ -505,8 +505,8 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET { if (lif_po->type != IF_T_PORT_CHANNEL) continue; - - if (!local_if_is_l3_mode(lif_po)) + + if (!local_if_is_l3_mode(lif_po)) { /* Is the L2 MLAG itf belong to a vlan?*/ LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) @@ -516,37 +516,37 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET continue; break; } - + if (!vlan_id_list) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", lif_po->name, vlan_id_list->vlan_itf->name); } - else + else { /* Is the ARP belong to a L3 mode MLAG itf?*/ if (ifindex != lif_po->ifindex) continue; ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", lif_po->name); } - + verify_arp = 1; - + break; } - + if (lif_po) break; } - + if (!(csm && lif_po)) return; if (!verify_arp) return; - + /* update lif ARP*/ TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { arp_info = (struct ARPMsg*) msg->buf; if (arp_info->ipv4_addr != arp_msg->ipv4_addr) continue; - + /* update ARP*/ if(arp_info->op_type != arp_msg->op_type || strcmp(arp_info->ifname, arp_msg->ifname)!=0 @@ -560,42 +560,42 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET show_ip_str(htonl(arp_msg->ipv4_addr))); } time(&arp_info->update_time); - + break; } - + /* enquene lif_msg (add)*/ - if (!msg) + if (!msg) { arp_msg->op_type = ARP_SYNC_LIF; - if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) { mlacp_enqueue_arp(csm, msg); - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr))); } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr))); } - + /* enqueue iccp_msg (add)*/ - if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { arp_msg->op_type = ARP_SYNC_ADD; - if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } - else + else ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } - + return; } @@ -605,7 +605,7 @@ void iccp_from_netlink_port_state_handler( char * ifname, int state) struct LocalInterface *lif_po = NULL; struct System *sys; int po_is_active = 0; - + if((sys = system_get_instance()) == NULL) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); @@ -613,7 +613,7 @@ void iccp_from_netlink_port_state_handler( char * ifname, int state) } po_is_active = (state == PORT_STATE_UP); - + /* traverse all CSM */ LIST_FOREACH(csm, &(sys->csm_list), next) { @@ -624,13 +624,13 @@ void iccp_from_netlink_port_state_handler( char * ifname, int state) mlacp_peerlink_down_handler(csm); else mlacp_peerlink_up_handler(csm); - + break; } - + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) { - if(lif_po->type == IF_T_PORT_CHANNEL && strncmp(lif_po->name, ifname, MAX_L_PORT_NAME) == 0) + if(lif_po->type == IF_T_PORT_CHANNEL && strncmp(lif_po->name, ifname, MAX_L_PORT_NAME) == 0) { mlacp_portchannel_state_handler(csm,lif_po,po_is_active); } @@ -646,15 +646,15 @@ int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, unsigned short type; memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); - - while (RTA_OK(rta, len)) + + while (RTA_OK(rta, len)) { type = rta->rta_type & ~flags; if ((type <= max) && (!tb[type])) tb[type] = rta; rta = RTA_NEXT(rta,len); } - + return 0; } @@ -668,26 +668,26 @@ int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) struct LocalInterface *lif = NULL; int msglen = 0; msglen = n->nlmsg_len; - while (NLMSG_OK(n, msglen)) + while (NLMSG_OK(n, msglen)) { struct ifinfomsg *ifm = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[IFLA_MAX+1]; - if (n->nlmsg_type != RTM_NEWLINK) + if (n->nlmsg_type != RTM_NEWLINK) { return ; } len -= NLMSG_LENGTH(sizeof(*ifm)); - if (len < 0) + if (len < 0) { ICCPD_LOG_WARN(__FUNCTION__, "BUG: wrong nlmsg len %d\n", len); return ; } if (ifm->ifi_family != AF_BRIDGE) - { + { return ; } @@ -696,12 +696,12 @@ int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len); /* if AF_SPEC isn't there, vlan table is not preset for this port */ - if (!tb[IFLA_AF_SPEC]) + if (!tb[IFLA_AF_SPEC]) { ICCPD_LOG_WARN(__FUNCTION__, "%d None\n", (ifm->ifi_index)); return ; - } - else + } + else { struct rtattr *i, *list = tb[IFLA_AF_SPEC]; int rem = RTA_PAYLOAD(list); @@ -712,8 +712,8 @@ int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) { vlan->vlan_removed = 1; } - - for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) + + for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { struct bridge_vlan_info *vinfo; @@ -731,7 +731,7 @@ int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) if(vlan->vlan_removed == 1) { ICCPD_LOG_DEBUG(__FUNCTION__, "Delete VLAN ID = %d from %s", vlan->vid, lif->name); - + LIST_REMOVE(vlan, port_next); free(vlan); } diff --git a/src/iccpd/src/iccp_main.c b/src/iccpd/src/iccp_main.c index eb1e25143d65..4a258a7e5f57 100644 --- a/src/iccpd/src/iccp_main.c +++ b/src/iccpd/src/iccp_main.c @@ -25,13 +25,15 @@ #include #include #include +#include +#include #include "../include/cmd_option.h" #include "../include/logger.h" #include "../include/scheduler.h" #include "../include/system.h" -int check_instance(char* pid_file_path) +int check_instance(char* pid_file_path) { int pid_file = 0; int rc = 0; @@ -40,34 +42,34 @@ int check_instance(char* pid_file_path) return -1; pid_file = open(pid_file_path, O_CREAT | O_RDWR, 0666); - if(pid_file <=0 ) + if(pid_file <=0 ) { fprintf(stderr, "Can't open a pid file. Terminate.\n"); close(pid_file); exit(EXIT_FAILURE); } - + rc = flock(pid_file, LOCK_EX | LOCK_NB); - if (rc) + if (rc) { - if (errno == EWOULDBLOCK) + if (errno == EWOULDBLOCK) { fprintf(stderr, "There is another instance running. Terminate.\n"); close(pid_file); exit(EXIT_FAILURE); } } - + return pid_file; } -void init_daemon(char* pid_file_path, int pid_file) +void init_daemon(char* pid_file_path, int pid_file) { pid_t pid, sid; pid = fork(); - if (pid < 0) + if (pid < 0) { fprintf(stderr, "Failed to enter daemon mode: %s\n", strerror(errno)); fprintf(stderr, "Please try to check your system resources.\n"); @@ -81,7 +83,7 @@ void init_daemon(char* pid_file_path, int pid_file) umask(0); sid = setsid(); - if (sid < 0) + if (sid < 0) { fprintf(stderr, "Failed to create a new SID for this program: %s\n", strerror(errno)); fprintf(stderr, "Please try to check your system resources.\n"); @@ -104,18 +106,97 @@ static inline int iccpd_make_rundir(void) int ret; ret = mkdir(ICCPD_RUN_DIR, 0755); - if (ret && errno != EEXIST) + if (ret && errno != EEXIST) { ICCPD_LOG_ERR(__FUNCTION__,"Failed to create directory \"%s\"", ICCPD_RUN_DIR); - + return -errno; } - + return 0; } -int main(int argc, char* argv[]) +void iccpd_signal_handler(int sig) +{ + int err; + struct System* sys = NULL; + const char warmboot_flag = 'w'; + + sys = system_get_instance(); + if (!sys) + { + return; + } + +retry: + err = write(sys->sig_pipe_w, &warmboot_flag, 1); + if (err == -1 && errno == EINTR) + goto retry; + + return; +} + +static int iccpd_signal_init(struct System* sys) +{ + int fds[2]; + int err; + sigset_t ss; + struct sigaction sa; + struct epoll_event event; + + err = pipe(fds); + if (err) + return -errno; + + sys->sig_pipe_r = fds[0]; + sys->sig_pipe_w = fds[1]; + + if (sigemptyset(&ss) < 0) { + ICCPD_LOG_ERR(__FUNCTION__, "sigemptyset(): %d", errno); + goto close_pipe; + } + + if (sigaddset(&ss, SIGUSR1) < 0) { + ICCPD_LOG_ERR(__FUNCTION__, "sigaddset(): %d", errno); + goto close_pipe; + } + + if (sigprocmask(SIG_UNBLOCK, &ss, NULL) < 0) { + ICCPD_LOG_ERR(__FUNCTION__, "sigprocmask(): %d", errno); + goto close_pipe; + } + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = iccpd_signal_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + if (sigaction(SIGUSR1, &sa, NULL) < 0) { + ICCPD_LOG_ERR(__FUNCTION__, "sigaction(): %d", errno); + goto close_pipe; + } + + event.data.fd = fds[0]; + event.events = EPOLLIN; + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, fds[0], &event); + if(err) + { + goto close_pipe; + } + + FD_SET( fds[0], &(sys->readfd)); + sys->readfd_count ++; + + return 0; + +close_pipe: + close(sys->sig_pipe_r); + close(sys->sig_pipe_w); + return err; +} + +int main(int argc, char* argv[]) { int pid_file_fd = 0; struct System* sys = NULL; @@ -125,43 +206,43 @@ int main(int argc, char* argv[]) err = iccpd_make_rundir(); if (err) return 0; - - if (getuid() != 0) + + if (getuid() != 0) { fprintf(stderr, "This program needs root permission to do device manipulation. " "Please use sudo to execute it or change your user to root.\n"); exit(EXIT_FAILURE); } - + parser.init(&parser); - if (parser.parse(&parser, argc, argv) != 0) + if (parser.parse(&parser, argc, argv) != 0) { parser.finalize(&parser); return -1; } - + pid_file_fd = check_instance(parser.pid_file_path); - if (pid_file_fd < 0) + if (pid_file_fd < 0) { fprintf(stderr, "Check instance with invalidate arguments, iccpd is terminated.\n"); parser.finalize(&parser); exit(EXIT_FAILURE); } - + sys = system_get_instance(); - if (!sys) + if (!sys) { fprintf(stderr, "Can't get a system instance, iccpd is terminated.\n"); parser.finalize(&parser); exit(EXIT_FAILURE); } - + /*if(!parser.console_log) init_daemon(parser.pid_file_path, pid_file_fd);*/ - - log_init(&parser); - + + log_init(&parser); + if (sys->log_file_path != NULL) free(sys->log_file_path); if (sys->cmd_file_path != NULL) @@ -175,13 +256,13 @@ int main(int argc, char* argv[]) sys->pid_file_fd = pid_file_fd; sys->telnet_port = parser.telnet_port; parser.finalize(&parser); - - ICCPD_LOG_INFO(__FUNCTION__, "Iccpd is started, process id = %d.", getpid()); + iccpd_signal_init(sys); + ICCPD_LOG_INFO(__FUNCTION__, "Iccpd is started, process id = %d. uid %d ", getpid(), getuid()); scheduler_init(); scheduler_start(); - scheduler_finalize(); system_finalize(); - log_finalize(); - + /*scheduler_finalize(); + log_finalize();*/ + return EXIT_SUCCESS; } diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c index a7e8980bfb5d..4ec49faf7c9e 100644 --- a/src/iccpd/src/iccp_netlink.c +++ b/src/iccpd/src/iccp_netlink.c @@ -72,7 +72,7 @@ static int iccp_ack_handler(struct nl_msg *msg, void *arg) bool *acked = arg; *acked = true; - + return NL_STOP; } @@ -83,7 +83,7 @@ static int iccp_seq_check_handler(struct nl_msg *msg, void *arg) if (hdr->nlmsg_seq != *seq) return NL_SKIP; - + return NL_OK; } @@ -124,10 +124,10 @@ int iccp_send_and_recv(struct System *sys, struct nl_msg *msg, */ acked = false; - while (!acked) + while (!acked) { ret = nl_recvmsgs(sys->genric_sock, cb); - if (ret) + if (ret) { err = ret; goto put_cb; @@ -155,10 +155,10 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) struct LocalInterface* local_if = NULL; char temp_buf[512]; int len = 0; - + sys = system_get_instance(); if (sys == NULL) - return 0; + return 0; genlmsg_parse(nlh, 0, attrs, TEAM_ATTR_MAX, NULL); @@ -179,47 +179,47 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) { if (!attrs[TEAM_ATTR_LIST_PORT]) return NL_SKIP; - - nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) + + nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) { - uint32_t member_index; + uint32_t member_index; - if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to parse nested attributes."); return NL_SKIP; } - if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) + if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) { ICCPD_LOG_ERR(__FUNCTION__, "ifindex port attribute not found."); return NL_SKIP; } - + member_index = nla_get_u32(port_attrs[TEAM_ATTR_PORT_IFINDEX]); local_if_member = local_if_find_by_ifindex(member_index); if(local_if_member == NULL) { - + ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance (%d).", local_if->name, member_index); continue; } - + if(port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) { local_if_member->po_id = -1; - mlacp_unbind_local_if(local_if_member); + mlacp_unbind_local_if(local_if_member); } else if ( local_if_member->po_id == -1) { - local_if_member->po_id = local_if->po_id; - mlacp_bind_local_if(local_if->csm, local_if_member); - } + local_if_member->po_id = local_if->po_id; + mlacp_bind_local_if(local_if->csm, local_if_member); + } } - - memset(temp_buf, 0, 512); + + memset(temp_buf, 0, 512); LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) { if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) @@ -227,19 +227,19 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) if(strlen(temp_buf) != 0) len += snprintf(temp_buf + len, 512-len,"%s", ","); - len += snprintf(temp_buf + len, 512-len,"%s",lif->name); + len += snprintf(temp_buf + len, 512-len,"%s",lif->name); } } - + if(strcmp(temp_buf,local_if->portchannel_member_buf)) { - memset(local_if->portchannel_member_buf, 0, 512); + memset(local_if->portchannel_member_buf, 0, 512); memcpy(local_if->portchannel_member_buf,temp_buf,sizeof(local_if->portchannel_member_buf)-1); if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /* portchannel member changed, update port isolate attribute*/ - update_peerlink_isolate_from_all_csm_lif(csm); + update_peerlink_isolate_from_all_csm_lif(csm); csm->isolate_update_time = time(NULL); } } @@ -255,21 +255,21 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) break; } } - + if (csm == NULL) return 0; - - nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) + + nla_for_each_nested(nl_port, attrs[TEAM_ATTR_LIST_PORT], i) { - uint32_t member_index; + uint32_t member_index; - if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to parse nested attributes."); return NL_SKIP; } - if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) + if (!port_attrs[TEAM_ATTR_PORT_IFINDEX]) { ICCPD_LOG_WARN(__FUNCTION__, "ifindex port attribute not found."); return NL_SKIP; @@ -287,19 +287,19 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) if(port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) { - local_if_member->po_id = -1; + local_if_member->po_id = -1; if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /*link removed from portchannel, must be enabled mac learn*/ set_peerlink_mlag_port_learn(local_if_member, 1); } - + continue; } else if ( local_if_member->po_id == -1) { - local_if_member->po_id = local_if->po_id; - + local_if_member->po_id = local_if->po_id; + if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /*link add to portchannel, must be disabled mac learn*/ @@ -307,22 +307,22 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) } } } - - memset(temp_buf, 0, 512); + + memset(temp_buf, 0, 512); LIST_FOREACH(lif, &(sys->lif_list), system_next) { if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) { if(strlen(temp_buf) != 0) len += snprintf(temp_buf + len, 512-len,"%s", ","); - - len += snprintf(temp_buf + len, 512-len,"%s",lif->name); - } + + len += snprintf(temp_buf + len, 512-len,"%s",lif->name); + } } - + if(strcmp(temp_buf,local_if->portchannel_member_buf)) { - memset(local_if->portchannel_member_buf, 0, 512); + memset(local_if->portchannel_member_buf, 0, 512); memcpy(local_if->portchannel_member_buf,temp_buf,sizeof(local_if->portchannel_member_buf)-1); if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) @@ -346,10 +346,10 @@ int iccp_genric_socket_team_family_get() if ((sys = system_get_instance()) == NULL ) return -1; - if (sys->family < 0) - { + if (sys->family < 0) + { sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); - while (sys->family < 0) + while (sys->family < 0) { sleep(1); @@ -357,25 +357,25 @@ int iccp_genric_socket_team_family_get() /*Only log error message 5 times*/ ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink family. %d of TEAM_GENL_NAME %s ", sys->family, TEAM_GENL_NAME); - sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); } grp_id = genl_ctrl_resolve_grp(sys->genric_sock, TEAM_GENL_NAME, TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME); - if (grp_id < 0) + if (grp_id < 0) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink multicast groups. %d", grp_id); } err = nl_socket_add_membership(sys->genric_event_sock, grp_id); - if (err < 0) + if (err < 0) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); } } - + return err; } @@ -388,7 +388,7 @@ int iccp_get_port_member_list(struct LocalInterface* lif) sys = system_get_instance(); if(sys == NULL) return 0; - + msg = nlmsg_alloc(); if (!msg) return -ENOMEM; @@ -399,7 +399,7 @@ int iccp_get_port_member_list(struct LocalInterface* lif) ICCPD_LOG_ERR(__FUNCTION__, "genric socket family get err err = %d . errno = %d", err , errno); return err; } - + genlmsg_put(msg, NL_AUTO_PID, sys->genric_sock_seq, sys->family, 0, 0, TEAM_CMD_PORT_LIST_GET, 0); nla_put_u32(msg, TEAM_ATTR_TEAM_IFINDEX, lif->ifindex); @@ -451,7 +451,7 @@ int iccp_netlink_if_hwaddr_set(uint32_t ifindex, uint8_t *addr, unsigned int add macArray[0],macArray[1],macArray[2], \ macArray[3],macArray[4],macArray[5]); -void iccp_set_portchannel_ipadd_mac(struct LocalInterface *lif, char * mac_addr ) +void iccp_set_interface_ipadd_mac(struct LocalInterface *lif, char * mac_addr ) { struct IccpSyncdHDr * msg_hdr; mclag_sub_option_hdr_t * sub_msg; @@ -462,9 +462,9 @@ void iccp_set_portchannel_ipadd_mac(struct LocalInterface *lif, char * mac_addr sys = system_get_instance(); if(sys == NULL) return; - + memset(msg_buf,0,4095); - + msg_hdr = (struct IccpSyncdHDr *)msg_buf; msg_hdr->ver= 1; msg_hdr->type = MCLAG_MSG_TYPE_SET_MAC; @@ -474,30 +474,31 @@ void iccp_set_portchannel_ipadd_mac(struct LocalInterface *lif, char * mac_addr sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC; - src_len = snprintf((char *)sub_msg->data, 512, "%s:%s/%d", lif->name,show_ip_str(htonl(lif->ipv4_addr)),lif->prefixlen); + /*src_len = snprintf((char *)sub_msg->data, 512, "%s:%s/%d", lif->name,show_ip_str(htonl(lif->ipv4_addr)),lif->prefixlen);*/ + src_len = snprintf((char *)sub_msg->data, 512, "%s", lif->name); sub_msg->op_len = src_len; /*sub msg dst */ msg_hdr->len += sub_msg->op_len; - msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_SET_MAC_DST; - - dst_len = strlen(mac_addr); - memcpy(sub_msg->data, mac_addr, dst_len); + + dst_len = strlen(mac_addr); + memcpy(sub_msg->data, mac_addr, dst_len); ICCPD_LOG_DEBUG(__FUNCTION__,"lif name %s address %s mac msg data %s %d \n", lif->name , show_ip_str(htonl(lif->ipv4_addr)), sub_msg->data ,dst_len); sub_msg->op_len = dst_len; - msg_hdr->len += sizeof(mclag_sub_option_hdr_t); - msg_hdr->len += sub_msg->op_len; + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; /*send msg*/ if(sys->sync_fd) - write(sys->sync_fd,msg_buf, msg_hdr->len); + write(sys->sync_fd,msg_buf, msg_hdr->len); - return; + return; } void update_if_ipmac_on_standby(struct LocalInterface* lif_po) @@ -508,42 +509,42 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) csm = lif_po->csm; struct LocalInterface* lif_Bri; char macaddr[64]; - int ret = 0; - + int ret = 0; + if (!csm) return; - + if(lif_po->type != IF_T_PORT_CHANNEL) - return; - - if (csm->role_type != STP_ROLE_STANDBY) + return; + + if (csm->role_type != STP_ROLE_STANDBY) { return; - } + } if(memcmp(MLACP(csm).remote_system.system_id, null_mac, ETHER_ADDR_LEN)==0) - return; - - /* set new mac*/ + return; + + /* set new mac*/ if(memcmp( lif_po->mac_addr, MLACP(csm).remote_system.system_id,ETHER_ADDR_LEN)!= 0) { /* backup old sysmac*/ memcpy(lif_po->mac_addr_ori, lif_po->mac_addr, ETHER_ADDR_LEN); - + ICCPD_LOG_DEBUG(__FUNCTION__, "%s Change the system-id of po%d from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", (csm->role_type == STP_ROLE_STANDBY)?"Standby":"Active", - lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], + lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], MLACP(csm).remote_system.system_id[0],MLACP(csm).remote_system.system_id[1],MLACP(csm).remote_system.system_id[2],MLACP(csm).remote_system.system_id[3],MLACP(csm).remote_system.system_id[4],MLACP(csm).remote_system.system_id[5]); - ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); + ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); if (ret != 0) { - ICCPD_LOG_ERR(__FUNCTION__, " set po %d mac error, ret = %d", ret); + ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", lif_po->name, ret); } /*set bridge mac back*/ - lif_Bri = local_if_find_by_name("Bridge"); + lif_Bri = local_if_find_by_name("Bridge"); if (lif_Bri) { ret = iccp_netlink_if_hwaddr_set(lif_Bri->ifindex, lif_po->mac_addr_ori, ETHER_ADDR_LEN); @@ -551,14 +552,14 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) { ICCPD_LOG_ERR(__FUNCTION__, "ip link set dev Bridge mac error, ret = %d", ret); } - } - } - + } + } + /*set portchannel ip mac */ memset(macaddr,0,64); - SET_MAC_STR(macaddr,MLACP(csm).remote_system.system_id); + SET_MAC_STR(macaddr,MLACP(csm).remote_system.system_id); if(local_if_is_l3_mode(lif_po)) - iccp_set_portchannel_ipadd_mac(lif_po, macaddr ); + iccp_set_interface_ipadd_mac(lif_po, macaddr ); else { LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) @@ -568,11 +569,17 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) /* If the po is under a vlan, update vlan mac*/ if(local_if_is_l3_mode(vlan->vlan_itf)) - { - iccp_set_portchannel_ipadd_mac(vlan->vlan_itf, macaddr ); + { + ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", vlan->vlan_itf->name, ret); + } + + iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr ); } } - } + } return; } @@ -584,40 +591,40 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) struct VLAN_ID *vlan = NULL; csm = lif_po->csm; char macaddr[64]; - int ret = 0; - + int ret = 0; + if (!csm) return; - + if(lif_po->type != IF_T_PORT_CHANNEL) - return; - - if (csm->role_type != STP_ROLE_STANDBY) + return; + + if (csm->role_type != STP_ROLE_STANDBY) { return; - } + } - /* recover mac to origin mac*/ + /* recover mac to origin mac*/ if(memcmp( lif_po->mac_addr, lif_po->mac_addr_ori, ETHER_ADDR_LEN)!= 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "%s Recove the system-id of po%d from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", (csm->role_type == STP_ROLE_STANDBY)?"Standby":"Active", - lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], + lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], lif_po->mac_addr_ori[0],lif_po->mac_addr_ori[1],lif_po->mac_addr_ori[2],lif_po->mac_addr_ori[3],lif_po->mac_addr_ori[4],lif_po->mac_addr_ori[5]); ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, lif_po->mac_addr_ori, ETHER_ADDR_LEN); if (ret != 0) { - ICCPD_LOG_ERR(__FUNCTION__, " set po %d mac error, ret = %d", ret); + ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", lif_po->name, ret); } - } - + } + /*set portchannel ip mac */ memset(macaddr,0,64); SET_MAC_STR(macaddr, lif_po->mac_addr_ori); if(local_if_is_l3_mode(lif_po)) - iccp_set_portchannel_ipadd_mac(lif_po, macaddr ); + iccp_set_interface_ipadd_mac(lif_po, macaddr ); else { LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) @@ -627,11 +634,17 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) /* If the po is under a vlan, update vlan mac*/ if(local_if_is_l3_mode(vlan->vlan_itf)) - { - iccp_set_portchannel_ipadd_mac(vlan->vlan_itf, macaddr); + { + ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, lif_po->mac_addr_ori, ETHER_ADDR_LEN); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", vlan->vlan_itf->name, ret); + } + + iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr); } } - } + } return; } @@ -648,12 +661,12 @@ void update_local_system_id(struct LocalInterface* local_if) } if (local_if->type != IF_T_PORT_CHANNEL) - return; + return; /* traverse all CSM */ LIST_FOREACH(csm, &(sys->csm_list), next) { - /* sync system info from one port-channel device*/ + /* sync system info from one port-channel device*/ if(memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) { memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); @@ -662,10 +675,10 @@ void update_local_system_id(struct LocalInterface* local_if) update_if_ipmac_on_standby(local_if); ICCPD_LOG_INFO(__FUNCTION__, "update csm %d local system id to mac %02x:%02x:%02x:%02x:%02x:%02x of %s ", csm->mlag_id, local_if->mac_addr[0],local_if->mac_addr[1], - local_if->mac_addr[2],local_if->mac_addr[3],local_if->mac_addr[4],local_if->mac_addr[5], local_if->name ); - } + local_if->mac_addr[2],local_if->mac_addr[3],local_if->mac_addr[4],local_if->mac_addr[5], local_if->name ); + } } - + return; } @@ -687,7 +700,7 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) ifname = rtnl_link_get_name(link); nl_addr = rtnl_link_get_addr(link); link_flag = rtnl_link_get_flags(link); - + if (nl_addr) addr_type = nl_addr_guess_family(nl_addr); @@ -719,33 +732,33 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) {VLAN_PREFIX, IF_T_VLAN}, {FRONT_PANEL_PORT_PREFIX, IF_T_PORT}, {VXLAN_TUNNEL_PREFIX, IF_T_VXLAN}, - {"Bri", IF_T_BRIDGE}, + {"Bri", IF_T_BRIDGE}, {NULL, 0} }; int i = 0; - for (i = 0; if_whitelist[i].ifname != NULL ; ++i) + for (i = 0; if_whitelist[i].ifname != NULL ; ++i) { if ((strncmp(ifname, - if_whitelist[i].ifname, strlen(if_whitelist[i].ifname)) == 0)) + if_whitelist[i].ifname, strlen(if_whitelist[i].ifname)) == 0)) { lif = local_if_create(ifindex, ifname, if_whitelist[i].type); - + lif->state = PORT_STATE_DOWN; - + if(IF_OPER_UP == op_state ) { lif->state = PORT_STATE_UP; } - - switch (addr_type) - { + + switch (addr_type) + { case AF_LLC: memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); update_local_system_id(lif); default: break; - } + } break; } @@ -760,21 +773,21 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) /*if(lif->type ==IF_T_PORT_CHANNEL)*/ iccp_from_netlink_port_state_handler(lif->name, lif->state); - ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); + ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); } else if (lif->state == PORT_STATE_UP &&( IF_OPER_UP != op_state||!(link_flag&IFF_LOWER_UP))) { lif->state = PORT_STATE_DOWN; /*if(lif->type ==IF_T_PORT_CHANNEL)*/ - iccp_from_netlink_port_state_handler(lif->name, lif->state); - - ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); + iccp_from_netlink_port_state_handler(lif->name, lif->state); + + ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); } - switch (addr_type) + switch (addr_type) { case AF_LLC: - if (memcmp(nl_addr_get_binary_addr(nl_addr), lif->mac_addr, ETHER_ADDR_LEN) != 0) + if (memcmp(nl_addr_get_binary_addr(nl_addr), lif->mac_addr, ETHER_ADDR_LEN) != 0) { memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); lif->port_config_sync = 1; @@ -783,9 +796,9 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) } default: break; - } + } } - + return; } @@ -811,7 +824,7 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) struct LocalInterface *lif; struct nlmsghdr *n = nlmsg_hdr(msg); - + if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) return 0; @@ -819,8 +832,8 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) if (ifa->ifa_family != AF_INET ) return 0; - - lif = local_if_find_by_ifindex(ifa->ifa_index); + + lif = local_if_find_by_ifindex(ifa->ifa_index); if (!lif) { return 0; @@ -829,7 +842,7 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) if (n->nlmsg_type == RTM_DELADDR) { lif->ipv4_addr = 0; - lif->prefixlen = 0; + lif->prefixlen = 0; lif->l3_mode = 0; } @@ -840,9 +853,9 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) struct rtattr *rth = IFA_RTA(ifa); int rtl = IFA_PAYLOAD(n); - while (rtl && RTA_OK(rth, rtl)) + while (rtl && RTA_OK(rth, rtl)) { - if (rth->rta_type == IFA_ADDRESS) + if (rth->rta_type == IFA_ADDRESS) { uint32_t ipaddr = ntohl(*((uint32_t *)RTA_DATA(rth))); lif->ipv4_addr = ipaddr; @@ -851,7 +864,7 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) lif->port_config_sync = 1; update_if_ipmac_on_standby(lif); ICCPD_LOG_DEBUG(__FUNCTION__," if name %s index %d address %s \n",lif->name,lif->ifindex,show_ip_str(htonl(lif->ipv4_addr))); - } + } rth = RTA_NEXT(rth, rtl); } @@ -868,35 +881,35 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) }; int ret; int retry = 1; - + if (!(sys = system_get_instance())) return -1; - - while (retry) + + while (retry) { retry = 0; ret = nl_send_simple(sys->route_sock, RTM_GETADDR, NLM_F_DUMP, - &rt_hdr, sizeof(rt_hdr)); + &rt_hdr, sizeof(rt_hdr)); - if (ret < 0) + if (ret < 0) { ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); return ret; } - + orig_cb = nl_socket_get_cb(sys->route_sock); cb = nl_cb_clone(orig_cb); nl_cb_put(orig_cb); - if (!cb) + if (!cb) { ICCPD_LOG_ERR(__FUNCTION__, "nl cb clone error."); return -ENOMEM; } - + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_local_if_addr_update, sys); ret = nl_recvmsgs(sys->route_sock, cb); nl_cb_put(cb); - if (ret < 0) + if (ret < 0) { ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error ret = %d errno = %d .", ret, errno); if (ret != -NLE_DUMP_INTR) @@ -904,7 +917,7 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) retry = 1; } } - + return ret; } @@ -913,12 +926,12 @@ static int iccp_route_event_handler(struct nl_msg *msg, void *arg) struct nlmsghdr *nlh = nlmsg_hdr(msg); unsigned int event = 1; - switch (nlh->nlmsg_type) + switch (nlh->nlmsg_type) { - case RTM_NEWLINK: - if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) + case RTM_NEWLINK: + if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type. "); - iccp_parse_if_vlan_info_from_netlink(nlh); + iccp_parse_if_vlan_info_from_netlink(nlh); break; case RTM_DELLINK: if (nl_msg_parse(msg, &iccp_event_handler_obj_input_dellink, NULL) < 0) @@ -931,7 +944,7 @@ static int iccp_route_event_handler(struct nl_msg *msg, void *arg) case RTM_NEWADDR: iccp_local_if_addr_update(msg, NULL); break; - + default: return NL_OK; } @@ -946,12 +959,12 @@ static int iccp_genric_event_handler(struct nl_msg *msg, void *arg) { struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - switch (gnlh->cmd) + switch (gnlh->cmd) { case TEAM_CMD_PORT_LIST_GET: return iccp_get_portchannel_member_list_handler(msg, NULL); } - + return NL_SKIP; } @@ -968,24 +981,24 @@ int iccp_system_init_netlink_socket() sys->genric_sock = nl_socket_alloc(); if (!sys->genric_sock) goto err_genric_sock_alloc; - + sys->genric_sock_seq = time(NULL); err = genl_connect(sys->genric_sock); if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sock sys->genric_sock."); - goto err_genric_sock_connect; + goto err_genric_sock_connect; } sys->genric_event_sock = nl_socket_alloc(); if (!sys->genric_event_sock) - goto err_genric_event_sock_alloc; + goto err_genric_event_sock_alloc; err = genl_connect(sys->genric_event_sock); if(err) { - ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->genric_event_sock."); - goto err_genric_event_sock_connect; + ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->genric_event_sock."); + goto err_genric_event_sock_connect; } sys->route_sock = nl_socket_alloc(); @@ -996,15 +1009,15 @@ int iccp_system_init_netlink_socket() goto err_route_sock_connect; err = nl_socket_set_buffer_size(sys->route_sock, 98304, 0); - if (err) + if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink route event sock."); goto err_route_sock_connect; } - + sys->route_event_sock = nl_socket_alloc(); if (!sys->route_event_sock) - goto err_route_event_sock_alloc; + goto err_route_event_sock_alloc; err = nl_connect(sys->route_event_sock, NETLINK_ROUTE); if(err) @@ -1014,7 +1027,7 @@ int iccp_system_init_netlink_socket() } err = nl_socket_set_buffer_size(sys->route_event_sock, 98304, 0); - if (err) + if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink route event sock."); goto err_route_event_sock_connect; @@ -1023,34 +1036,34 @@ int iccp_system_init_netlink_socket() val = NETLINK_BROADCAST_SEND_ERROR; err = setsockopt(nl_socket_get_fd(sys->genric_event_sock), SOL_NETLINK, NETLINK_BROADCAST_ERROR, &val, sizeof(val)); - if (err) + if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed set NETLINK_BROADCAST_ERROR on netlink event sock."); goto err_return; } err = nl_socket_set_buffer_size(sys->genric_sock, 98304, 0); - if (err) + if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink sock."); goto err_return; } - + err = nl_socket_set_buffer_size(sys->genric_event_sock, 98304, 0); - if (err) + if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink event sock."); goto err_return; } #if 0 sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); - while (sys->family < 0) + while (sys->family < 0) { sleep(1); log_err_period++; /*If no portchannel configuration, teamd will not started, genl_ctrl_resolve() will return <0 forever */ /*Only log error message 5 times*/ - if(log_err_period == 1 && log_err_time < 5) + if(log_err_period == 1 && log_err_time < 5) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink family. %d of TEAM_GENL_NAME %s ", sys->family, TEAM_GENL_NAME); log_err_time++; @@ -1058,23 +1071,23 @@ int iccp_system_init_netlink_socket() else { /*Log error message every 30s per time*/ - if(log_err_period == 30) + if(log_err_period == 30) log_err_period = 0; } - + sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); } grp_id = genl_ctrl_resolve_grp(sys->genric_sock, TEAM_GENL_NAME, TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME); - if (grp_id < 0) + if (grp_id < 0) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink multicast groups. %d", grp_id); goto err_return; } err = nl_socket_add_membership(sys->genric_event_sock, grp_id); - if (err < 0) + if (err < 0) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); goto err_return; @@ -1089,47 +1102,47 @@ int iccp_system_init_netlink_socket() iccp_route_event_handler, sys); err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_NEIGH); - if (err < 0) + if (err < 0) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); goto err_return; - } + } err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_LINK); - if (err < 0) + if (err < 0) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); goto err_return; - } + } err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_IPV4_IFADDR); - if (err < 0) + if (err < 0) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); goto err_return; - } + } /*receive arp packet socket*/ sys->arp_receive_fd = socket(PF_PACKET, SOCK_DGRAM, 0); - if (sys->arp_receive_fd < 0) + if (sys->arp_receive_fd < 0) { ICCPD_LOG_ERR(__FUNCTION__,"socket error "); goto err_return; } - if (1) + if (1) { struct sockaddr_ll sll; memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_protocol = htons(ETH_P_ARP); sll.sll_ifindex = 0; - if (bind(sys->arp_receive_fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) + if (bind(sys->arp_receive_fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) { ICCPD_LOG_ERR(__FUNCTION__,"socket bind error"); goto err_return; } - } + } goto succes_return; @@ -1137,27 +1150,41 @@ int iccp_system_init_netlink_socket() err_route_event_sock_connect: nl_socket_free(sys->route_event_sock); - -err_route_sock_alloc: + +err_route_sock_alloc: err_route_sock_connect: - nl_socket_free(sys->route_sock); - -err_route_event_sock_alloc: + nl_socket_free(sys->route_sock); + +err_route_event_sock_alloc: err_genric_event_sock_connect: nl_socket_free(sys->genric_event_sock); -err_genric_event_sock_alloc: +err_genric_event_sock_alloc: err_genric_sock_connect: nl_socket_free(sys->genric_sock); return err; - + err_genric_sock_alloc: succes_return: return 0; } +void iccp_system_dinit_netlink_socket() +{ + struct System* sys = NULL; + + if ((sys = system_get_instance()) == NULL ) + return ; + + nl_socket_free(sys->route_event_sock); + nl_socket_free(sys->route_sock); + nl_socket_free(sys->genric_event_sock); + nl_socket_free(sys->genric_sock); + return; +} + static int iccp_get_netlink_genic_sock_event_fd(struct System *sys) { return nl_socket_get_fd(sys->genric_event_sock); @@ -1166,14 +1193,14 @@ static int iccp_get_netlink_genic_sock_event_fd(struct System *sys) static int iccp_netlink_genic_sock_event_handler(struct System *sys) { int ret = 0; - + ret = nl_recvmsgs_default(sys->genric_event_sock); if(ret) { - sys->need_sync_team_again = 1; - ICCPD_LOG_DEBUG(__FUNCTION__, "genric_event_sock %d recvmsg error ret = %d ",nl_socket_get_fd(sys->genric_event_sock), ret); + sys->need_sync_team_again = 1; + ICCPD_LOG_DEBUG(__FUNCTION__, "genric_event_sock %d recvmsg error ret = %d ",nl_socket_get_fd(sys->genric_event_sock), ret); } - + return ret; } @@ -1200,28 +1227,28 @@ static int iccp_receive_arp_packet_handler(struct System *sys) n = recvfrom(sys->arp_receive_fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&sll, &sll_len); - if (n < 0) + if (n < 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "arp recvfrom: %s",buf); return -1; } /* Sanity checks */ - /*Only process ARPOP_REPLY*/ - if (n < sizeof(*a) || + /*Only process ARPOP_REPLY*/ + if (n < sizeof(*a) || a->ar_op != htons(ARPOP_REPLY) || a->ar_pln != 4 || a->ar_pro != htons(ETH_P_IP) || a->ar_hln != sll.sll_halen || sizeof(*a) + 2*4 + 2*a->ar_hln > n) return 0; - + ifindex = sll.sll_ifindex; memcpy(mac_addr, (char*)(a+1), ETHER_ADDR_LEN); memcpy(&addr, (char*)(a+1) + a->ar_hln, 4); - + do_arp_update (ifindex, ntohl(addr), mac_addr); - + return 0; } @@ -1235,25 +1262,25 @@ void iccp_netlink_sync_again() if(sys->need_sync_netlink_again) { - sys->need_sync_netlink_again = 0; - + sys->need_sync_netlink_again = 0; + /*Get kernel interface and port */ - iccp_sys_local_if_list_get_init(); + iccp_sys_local_if_list_get_init(); } - + if(sys->need_sync_team_again) { - sys->need_sync_team_again = 0; - - LIST_FOREACH(lif, &(sys->lif_list), system_next) + sys->need_sync_team_again = 0; + + LIST_FOREACH(lif, &(sys->lif_list), system_next) { if (lif->type == IF_T_PORT_CHANNEL) { iccp_get_port_member_list(lif); } - } + } } - + return; } @@ -1262,18 +1289,18 @@ static int iccp_netlink_route_sock_event_handler(struct System *sys) int ret = 0; ret = nl_recvmsgs_default(sys->route_event_sock); - + if(ret) { - sys->need_sync_netlink_again = 1; - ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d recvmsg error ret = %d errno = %d ",nl_socket_get_fd(sys->route_event_sock), ret, errno); + sys->need_sync_netlink_again = 1; + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d recvmsg error ret = %d errno = %d ",nl_socket_get_fd(sys->route_event_sock), ret, errno); } /*get netlink info again when error happens */ if (ret ==0 && sys->need_sync_netlink_again == 1) { iccp_netlink_sync_again(); } - + return ret; } @@ -1329,27 +1356,27 @@ int iccp_init_netlink_event_fd(struct System *sys) efd = epoll_create1(0); if (efd == -1) return -errno; - for (i = 0; i < ICCP_EVENT_FDS_COUNT; i++) + for (i = 0; i < ICCP_EVENT_FDS_COUNT; i++) { int fd = iccp_eventfds[i].get_fd(sys); event.data.fd = fd; event.events = EPOLLIN; err = epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event); - if (err == -1) + if (err == -1) { err = -errno; goto close_efd; } } - + sys->epoll_fd = efd; - + return 0; close_efd: close(efd); - + return err; } @@ -1369,17 +1396,18 @@ int iccp_handle_events(struct System * sys) int i; int err; int max_nfds; + max_nfds = ICCP_EVENT_FDS_COUNT+sys->readfd_count; - + nfds = epoll_wait(sys->epoll_fd, events, max_nfds, EPOLL_TIMEOUT_MSEC); - + /* Go over list of event fds and handle them sequentially */ - for (i = 0; i < nfds; i++) + for (i = 0; i < nfds; i++) { - for (n = 0; n < ICCP_EVENT_FDS_COUNT; n++) + for (n = 0; n < ICCP_EVENT_FDS_COUNT; n++) { const struct iccp_eventfd *eventfd = &iccp_eventfds[n]; - if (events[i].data.fd == eventfd->get_fd(sys)) + if (events[i].data.fd == eventfd->get_fd(sys)) { err = eventfd->event_handler(sys); if (err) @@ -1404,7 +1432,14 @@ int iccp_handle_events(struct System * sys) if (events[i].data.fd == sys->sync_fd) { - iccp_receive_fdb_handler_from_syncd(sys); + iccp_receive_fdb_handler_from_syncd(sys); + + continue; + } + + if (events[i].data.fd == sys->sig_pipe_r) + { + iccp_receive_signal_handler(sys); continue; } @@ -1421,7 +1456,7 @@ int iccp_handle_events(struct System * sys) } } } - + return 0; } diff --git a/src/iccpd/src/logger.c b/src/iccpd/src/logger.c index c495b3452ebb..dfa4bcbbcb1d 100644 --- a/src/iccpd/src/logger.c +++ b/src/iccpd/src/logger.c @@ -30,15 +30,15 @@ static uint32_t _iccpd_log_level_map[] = { - LOG_DEBUG, - LOG_INFO, - LOG_NOTICE, - LOG_WARNING, - LOG_ERR, - LOG_CRIT, + LOG_DEBUG, + LOG_INFO, + LOG_NOTICE, + LOG_WARNING, + LOG_ERR, + LOG_CRIT, }; -static char* log_level_to_string(int level) +static char* log_level_to_string(int level) { switch (level) { @@ -55,36 +55,36 @@ static char* log_level_to_string(int level) case DEBUG_LOG_LEVEL: return "DEBUG"; } - + return "INFO"; } -struct LoggerConfig* logger_get_configuration() +struct LoggerConfig* logger_get_configuration() { static struct LoggerConfig config; - if (config.init == 0) + if (config.init == 0) { config.console_log_enabled = 0; config.log_level = DEBUG_LOG_LEVEL; config.init = 1; } - + return &config; } -void log_init(struct CmdOptionParser* parser) +void log_init(struct CmdOptionParser* parser) { struct LoggerConfig* config = logger_get_configuration(); config->console_log_enabled = parser->console_log; } -void log_finalize() +void log_finalize() { /*do nothing*/ } -void write_log(const int level, const char* tag, const char* format, ...) +void write_log(const int level, const char* tag, const char* format, ...) { struct LoggerConfig* config = logger_get_configuration(); char buf[LOGBUF_SIZE]; @@ -92,12 +92,12 @@ void write_log(const int level, const char* tag, const char* format, ...) unsigned int prefix_len; unsigned int avbl_buf_len; unsigned int print_len; - + #if 0 if (!config->console_log_enabled) return; -#endif - +#endif + if (level < config->log_level) return; @@ -118,7 +118,7 @@ void write_log(const int level, const char* tag, const char* format, ...) buf[prefix_len+print_len] = '\0'; ICCPD_UTILS_SYSLOG(_iccpd_log_level_map[level], "%s", buf); - + return; } diff --git a/src/iccpd/src/mclagdctl/mclagdctl.c b/src/iccpd/src/mclagdctl/mclagdctl.c index ae3aeb54d529..71af888e404b 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.c +++ b/src/iccpd/src/mclagdctl/mclagdctl.c @@ -226,9 +226,9 @@ int mclagdctl_parse_dump_state(char *msg, int data_len) fprintf(stdout,"%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR"); if (state_info->mclag_id <= 0) - fprintf(stdout,"%s: %s\n", "Mclag id", "UNKNOWN"); + fprintf(stdout,"%s: %s\n", "Domain id", "Unknown"); else - fprintf(stdout,"%s: %d\n" ,"Mclag id", state_info->mclag_id); + fprintf(stdout,"%s: %d\n" ,"Domain id", state_info->mclag_id); fprintf(stdout,"%s: %s\n", "Local Ip", state_info->local_ip); fprintf(stdout,"%s: %s\n", "Peer Ip", state_info->peer_ip); @@ -241,13 +241,13 @@ int mclagdctl_parse_dump_state(char *msg, int data_len) state_info->peer_link_mac[4], state_info->peer_link_mac[5]); if (state_info->role == 0) - fprintf(stdout,"%s: %s\n", "Role", "NONE"); + fprintf(stdout,"%s: %s\n", "Role", "None"); else if (state_info->role == 1) - fprintf(stdout,"%s: %s\n", "Role", "ACTIVE"); + fprintf(stdout,"%s: %s\n", "Role", "Active"); else if (state_info->role == 2) - fprintf(stdout,"%s: %s\n", "Role", "STANDBY"); + fprintf(stdout,"%s: %s\n", "Role", "Standby"); - fprintf(stdout,"%s: %s\n", "Enabled PortChannel", state_info->enabled_po); + fprintf(stdout,"%s: %s\n", "MCLAG Interface", state_info->enabled_po); } @@ -420,13 +420,13 @@ int mclagdctl_parse_dump_local_portlist(char *msg, int data_len) fprintf(stdout,"%s: %s\n", "IPv4Address", lif_info->ipv4_addr); fprintf(stdout,"%s: %d\n" ,"Prefixlen", lif_info->prefixlen); fprintf(stdout,"%s: %s\n", "State", lif_info->state); - fprintf(stdout,"%s: %d\n" ,"L3Mode", lif_info->l3_mode); - fprintf(stdout,"%s: %d\n" ,"IsPeerlink", lif_info->is_peer_link); - fprintf(stdout,"%s: %s\n", "PortchannelMem", lif_info->portchannel_member_buf); - fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); - fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", lif_info->po_active); - fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state); - fprintf(stdout,"%s: %d\n" ,"IsIsolateWithPeerlink", lif_info->isolate_to_peer_link); + fprintf(stdout,"%s: %s\n" ,"IsL3Interface", lif_info->l3_mode ? "Yes":"No"); + fprintf(stdout,"%s: %s\n" ,"IsPeerlink", lif_info->is_peer_link ? "Yes":"No"); + fprintf(stdout,"%s: %s\n", "MemberPorts", lif_info->portchannel_member_buf); + /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); + fprintf(stdout,"%s: %d\n" ,"PortchannelIsUp", lif_info->po_active); + fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state);*/ + fprintf(stdout,"%s: %s\n" ,"IsIsolateWithPeerlink", lif_info->isolate_to_peer_link ? "Yes":"No"); fprintf(stdout,"%s: %s\n" ,"VlanList", lif_info->vlanlist); } else @@ -435,7 +435,7 @@ int mclagdctl_parse_dump_local_portlist(char *msg, int data_len) fprintf(stdout,"%s: %s\n", "Type", lif_info->type); fprintf(stdout,"%s: %s\n", "PortName", lif_info->name); fprintf(stdout,"%s: %s\n", "State", lif_info->state); - fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); + /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id);*/ } for (pos = 0; pos < 60; ++pos) @@ -492,8 +492,8 @@ int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len) pif_info->mac_addr[4], pif_info->mac_addr[5]); fprintf(stdout,"%s: %s\n", "State", pif_info->state); - fprintf(stdout,"%s: %d\n" ,"PortchannelId", pif_info->po_id); - fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", pif_info->po_active); + /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", pif_info->po_id); + fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", pif_info->po_active);*/ for (pos = 0; pos < 60; ++pos) fprintf(stdout, "-"); @@ -749,7 +749,7 @@ int main(int argc, char **argv) } reply = (struct mclagd_reply_hdr *)rcv_buf; - + if (reply->info_type != cmd_type->info_type) { fprintf(stderr, "Reply info type from mclagd error\n"); diff --git a/src/iccpd/src/mlacp_fsm.c b/src/iccpd/src/mlacp_fsm.c index 2b2eccd12298..3aff7801e670 100644 --- a/src/iccpd/src/mlacp_fsm.c +++ b/src/iccpd/src/mlacp_fsm.c @@ -459,6 +459,16 @@ static void mlacp_sync_recv_heartbeat(struct CSM* csm, struct Msg* msg) return; } +static void mlacp_sync_recv_warmboot(struct CSM* csm, struct Msg* msg) +{ + struct mLACPWarmbootTLV *tlv = NULL; + + tlv = (struct mLACPWarmbootTLV *)(&msg->buf[sizeof(ICCHdr)]); + mlacp_fsm_update_warmboot(csm, tlv); + + return; +} + /***************************************** * MLACP Init * @@ -883,6 +893,9 @@ static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg) case TLV_T_MLACP_HEARTBEAT: mlacp_sync_recv_heartbeat(csm, msg); break; + case TLV_T_MLACP_WARMBOOT_FLAG: + mlacp_sync_recv_warmboot(csm, msg); + break; } /*ICCPD_LOG_DEBUG("mlacp_fsm", " [Sync Recv] %s... DONE", get_tlv_type_string(icc_param->type));*/ @@ -1132,5 +1145,13 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) /* Send ARP info if any*/ mlacp_sync_send_syncArpInfo(csm); + /*If peer is warm reboot*/ + if(csm->peer_warm_reboot_time != 0) + { + /*Peer warm reboot timeout, recover to normal reboot*/ + if((time(NULL) - csm->peer_warm_reboot_time) >= 90) + csm->peer_warm_reboot_time = 0; + } + return; } \ No newline at end of file diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index 42810f2027a9..902723f7c147 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -635,7 +635,7 @@ void peerlink_port_isolate_cleanup(struct CSM* csm) if (!csm) return; - + /* Clean all port block*/ LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) { @@ -1239,18 +1239,24 @@ static void mlacp_conn_handler_fdb (struct CSM* csm) void mlacp_peer_conn_handler(struct CSM* csm) { struct LocalInterface *lif = NULL; - struct VLAN_ID *vlan = NULL; static int first_time = 0; + struct System* sys = NULL; if (!csm) return; - + + if((sys = system_get_instance()) == NULL) + return; + set_peerlink_mlag_port_learn(csm->peer_link_if, 0); + /*If peer connect again, don't flush FDB*/ if(first_time == 0) { first_time = 1; - mlacp_clean_fdb(); + /*If warm reboot, don't flush FDB*/ + if(sys->warmboot_start != WARM_REBOOT) + mlacp_clean_fdb(); } iccp_get_fdb_change_from_syncd(); @@ -1301,10 +1307,26 @@ void mlacp_peer_disconn_handler(struct CSM* csm) struct LocalInterface* lif = NULL; struct Msg* msg = NULL; struct MACMsg* mac_msg = NULL; + struct System* sys = NULL; if (!csm) return; + if((sys = system_get_instance()) == NULL) + return; + + /*If warm reboot, don't change FDB and MAC address*/ + if(sys->warmboot_exit == WARM_REBOOT) + return; + + /*If peer is warm reboot, don't change FDB and MAC address*/ + if(csm->peer_warm_reboot_time != 0) + { + /*If peer disconnected, recover peer to normal reboot for next time*/ + csm->peer_warm_reboot_time = 0; + return; + } + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { mac_msg = (struct MACMsg*) msg->buf; @@ -1458,7 +1480,7 @@ int iccp_connect_syncd() fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { - if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to create unix socket: %s", strerror(errno)); + if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to create unix socket: %s", strerror(errno)); goto conn_fail; } @@ -1473,7 +1495,7 @@ int iccp_connect_syncd() ret = connect(fd, (struct sockaddr *)&serv, sizeof(serv)); if (ret < 0) { - if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to connect to mclag syncd: errno str %s", strerror(errno)); + if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to connect to mclag syncd: errno str %s", strerror(errno)); close(fd); goto conn_fail; } @@ -1798,27 +1820,28 @@ void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uin return -1; } - if (msg_hdr->type != MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION) + if (msg_hdr->type == MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION) { - ICCPD_LOG_DEBUG(__FUNCTION__, "msg type wrong!!!!! "); - return -1; - } + count =( msg_hdr->len- sizeof(struct IccpSyncdHDr ))/sizeof(struct mclag_fdb_info); + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d ",count ); + for (i =0; ivid, mac_info->mac, mac_info->port_name, mac_info->op_type); + lif = local_if_find_by_name(mac_info->port_name); + + /*if (!lif ||lif->type != IF_T_PORT_CHANNEL)*/ + if (!lif) + continue; - count =( msg_hdr->len- sizeof(struct IccpSyncdHDr ))/sizeof(struct mclag_fdb_info); - ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d ",count ); - for (i =0; imac, mac_info->vid, mac_info->port_name, mac_info->type, mac_info->op_type); + } + } + else { - mac_info = (struct mclag_fdb_info *)&msg_buf[sizeof(struct IccpSyncdHDr )+ i * sizeof(struct mclag_fdb_info)]; - ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d vid %d mac %s port %s optype %d ",i, mac_info->vid, mac_info->mac, mac_info->port_name, mac_info->op_type); - lif = local_if_find_by_name(mac_info->port_name); - - /*if (!lif ||lif->type != IF_T_PORT_CHANNEL)*/ - if (!lif) - continue; - - do_mac_update_from_syncd(mac_info->mac, mac_info->vid, mac_info->port_name, mac_info->type, mac_info->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "recv unknown type msg " ); } - + return 0; } diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c index aa3ae8f8f006..48b97ab3af64 100644 --- a/src/iccpd/src/mlacp_sync_prepare.c +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -556,6 +556,48 @@ int mlacp_prepare_for_heartbeat(struct CSM* csm,char* buf, size_t max_buf_size) return msg_len; } +/***************************************** +* Prepare Send warm-reboot flag +* +* ***************************************/ +int mlacp_prepare_for_warm_reboot(struct CSM* csm,char* buf, size_t max_buf_size) +{ + struct System* sys = NULL; + ICCHdr* icc_hdr = (ICCHdr*) buf; + struct mLACPWarmbootTLV* tlv = (struct mLACPWarmbootTLV*) &buf[sizeof(ICCHdr)]; + size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPWarmbootTLV); + + if(csm == NULL) + return -1; + + if(buf == NULL) + return -1; + + if(msg_len > max_buf_size) + return -1; + + if((sys = system_get_instance()) == NULL) + return -1; + + /* Prepare for sync request */ + memset(buf, 0, max_buf_size); + + icc_hdr = (ICCHdr*) buf; + tlv = (struct mLACPWarmbootTLV*) &buf[sizeof(ICCHdr)]; + + /* ICC header */ + mlacp_fill_icc_header(csm, icc_hdr, msg_len); + + /* System Config TLV */ + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_WARMBOOT_FLAG); + + tlv->icc_parameter.len = htons(sizeof(struct mLACPWarmbootTLV) - sizeof(ICCParameter)); + tlv->warmboot = 0x1; + return msg_len; +} + /***************************************** * Tool : Prepare ICC Header * diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c index fb1e4b0b8856..af68244edd56 100644 --- a/src/iccpd/src/mlacp_sync_update.c +++ b/src/iccpd/src/mlacp_sync_update.c @@ -641,4 +641,16 @@ int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv) return 0; } +/***************************************** +* warm-reboot flag Update +*****************************************/ +int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv) +{ + if (!csm || !tlv) + return -255; + + time(&csm->peer_warm_reboot_time); + + return 0; +} diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c index 65caf24081a6..cec97accac5a 100644 --- a/src/iccpd/src/scheduler.c +++ b/src/iccpd/src/scheduler.c @@ -270,6 +270,27 @@ int scheduler_server_accept() return 0; } +void iccp_get_start_type(struct System* sys) +{ + FILE* fp; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + + fp = fopen("/proc/cmdline", "r"); + if (!fp) + { + ICCPD_LOG_DEBUG(__FUNCTION__,"Error: Can't open file /proc/cmdline!"); + return; + } + + fread(g_csm_buf, CSM_BUFFER_SIZE, 1, fp); + (void)fclose(fp); + + if(strstr(g_csm_buf, "SONIC_BOOT_TYPE=warm")) + sys->warmboot_start = WARM_REBOOT; + + return; +} + /* scheduler initialization */ void scheduler_init() { @@ -277,7 +298,8 @@ void scheduler_init() if (!(sys = system_get_instance())) return; - + + iccp_get_start_type(sys); /*Get kernel interface and port */ iccp_sys_local_if_list_get_init(); iccp_sys_local_if_list_get_addr(); @@ -307,10 +329,59 @@ void scheduler_init() return; } +extern int mlacp_prepare_for_warm_reboot(struct CSM* csm,char* buf, size_t max_buf_size); +void mlacp_sync_send_warmboot_flag() +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + int msg_len = 0; + + if((sys = system_get_instance()) == NULL) + return; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + if(MLACP(csm).current_state==MLACP_STATE_EXCHANGE) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_warm_reboot(csm, g_csm_buf, CSM_BUFFER_SIZE); + iccp_csm_send(csm, g_csm_buf, msg_len); + } + } + + return; +} + +int iccp_receive_signal_handler(struct System* sys) +{ + char ctrl_byte; + int err = 0; + + err = read(sys->sig_pipe_r, &ctrl_byte, 1); + if (err == -1) + { + ICCPD_LOG_DEBUG(__FUNCTION__,"Read sig_pipe_r fail !"); + return err; + } + + switch(ctrl_byte) + { + case 'w': + /*send packet to peer*/ + mlacp_sync_send_warmboot_flag(); + sys->warmboot_exit = WARM_REBOOT; + break; + default: + break; + } + + return 0; +} + /* Thread fetch to call */ void scheduler_loop() { - struct System* sys = NULL; + struct System* sys = NULL; if ((sys = system_get_instance()) == NULL) return; @@ -325,7 +396,13 @@ void scheduler_loop() /*handle socket slelect event ,If no message received, it will block 0.1s*/ iccp_handle_events(sys); /*csm, app state machine transit */ - scheduler_transit_fsm(); + scheduler_transit_fsm(); + + if (sys->warmboot_exit == WARM_REBOOT) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "EXIT ......"); + return; + } } return; diff --git a/src/iccpd/src/system.c b/src/iccpd/src/system.c index 79d68b5c7956..c525609b8c36 100644 --- a/src/iccpd/src/system.c +++ b/src/iccpd/src/system.c @@ -58,6 +58,8 @@ void system_init(struct System* sys) sys->arp_receive_fd = -1; sys->epoll_fd = -1; sys->family = -1; + sys->warmboot_start = 0; + sys->warmboot_exit = 0; LIST_INIT(&(sys->csm_list)); LIST_INIT(&(sys->lif_list)); LIST_INIT(&(sys->lif_purge_list)); @@ -100,14 +102,18 @@ void system_finalize() while (!LIST_EMPTY(&(sys->lif_list))) { local_if = LIST_FIRST(&(sys->lif_list)); + LIST_REMOVE(local_if, system_next); local_if_finalize(local_if); } while (!LIST_EMPTY(&(sys->lif_purge_list))) { - local_if = LIST_FIRST(&(sys->lif_list)); + local_if = LIST_FIRST(&(sys->lif_purge_list)); + LIST_REMOVE(local_if, system_purge_next); local_if_finalize(local_if); } + iccp_system_dinit_netlink_socket(); + if (sys->log_file_path != NULL ) free(sys->log_file_path); if (sys->cmd_file_path != NULL ) @@ -124,6 +130,11 @@ void system_finalize() close(sys->sync_ctrl_fd); if(sys->arp_receive_fd > 0) close(sys->arp_receive_fd); + if(sys->sig_pipe_r > 0) + close(sys->sig_pipe_r); + if(sys->sig_pipe_w > 0) + close(sys->sig_pipe_w); + if(sys->epoll_fd) close(sys->epoll_fd); From 896aa416da40f188a3167f92f0a71b0a5956e866 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Mon, 22 Jul 2019 20:08:48 -0700 Subject: [PATCH 09/23] merge to master branch and reformat iccpd file Signed-off-by: shine.chen --- dockers/docker-iccpd/Dockerfile.j2 | 29 +- dockers/docker-iccpd/iccpd.j2 | 1 + src/iccpd/include/app_csm.h | 58 +- src/iccpd/include/cmd_option.h | 106 +- src/iccpd/include/iccp_cli.h | 58 +- src/iccpd/include/iccp_cmd.h | 44 +- src/iccpd/include/iccp_cmd_show.h | 46 +- src/iccpd/include/iccp_consistency_check.h | 47 +- src/iccpd/include/iccp_csm.h | 87 +- src/iccpd/include/iccp_ifm.h | 48 +- src/iccpd/include/iccp_netlink.h | 36 +- src/iccpd/include/logger.h | 75 +- src/iccpd/include/mlacp_fsm.h | 64 +- src/iccpd/include/mlacp_link_handler.h | 50 +- src/iccpd/include/mlacp_sync_prepare.h | 68 +- src/iccpd/include/mlacp_sync_update.h | 48 +- src/iccpd/include/mlacp_tlv.h | 398 +++--- src/iccpd/include/msg_format.h | 305 +++-- src/iccpd/include/port.h | 93 +- src/iccpd/include/scheduler.h | 44 +- src/iccpd/include/system.h | 55 +- src/iccpd/src/app_csm.c | 89 +- src/iccpd/src/cmd_option.c | 86 +- src/iccpd/src/iccp_cli.c | 275 +++- src/iccpd/src/iccp_cmd.c | 96 +- src/iccpd/src/iccp_cmd_show.c | 124 +- src/iccpd/src/iccp_consistency_check.c | 106 +- src/iccpd/src/iccp_csm.c | 247 ++-- src/iccpd/src/iccp_ifm.c | 209 +-- src/iccpd/src/iccp_main.c | 80 +- src/iccpd/src/iccp_netlink.c | 451 ++++--- src/iccpd/src/logger.c | 58 +- src/iccpd/src/mclagdctl/mclagdctl.c | 575 ++++---- src/iccpd/src/mclagdctl/mclagdctl.h | 86 +- src/iccpd/src/mlacp_fsm.c | 509 +++---- src/iccpd/src/mlacp_link_handler.c | 1412 ++++++++++---------- src/iccpd/src/mlacp_sync_prepare.c | 463 +++---- src/iccpd/src/mlacp_sync_update.c | 385 +++--- src/iccpd/src/port.c | 330 ++--- src/iccpd/src/scheduler.c | 399 +++--- src/iccpd/src/system.c | 133 +- 41 files changed, 4137 insertions(+), 3736 deletions(-) diff --git a/dockers/docker-iccpd/Dockerfile.j2 b/dockers/docker-iccpd/Dockerfile.j2 index 41dc0dc9a258..ce3969f29da5 100644 --- a/dockers/docker-iccpd/Dockerfile.j2 +++ b/dockers/docker-iccpd/Dockerfile.j2 @@ -1,16 +1,25 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %} FROM docker-config-engine-stretch +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + ## Make apt-get non-interactive ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get update - -RUN apt-get install -f -y libdbus-1-3 libdaemon0 libjansson4 +RUN apt-get update && \ + apt-get install -f -y \ + libdbus-1-3 \ + libdaemon0 \ + libpython2.7 \ + # Install redis-tools dependencies + # TODO: implicitly install dependencies + libatomic1 \ + libjemalloc1 \ + liblua5.1-0 \ + lua-bitop \ + lua-cjson -## Install redis-tools dependencies -## TODO: implicitly install dependencies -RUN apt-get -y install libjemalloc1 -RUN apt-get -y install libpython2.7 RUN apt-get -y install ebtables RUN apt-get -y install -f kmod @@ -30,7 +39,9 @@ COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] COPY ["iccpd.j2", "/usr/share/sonic/templates/"] RUN chmod +x /usr/bin/start.sh /usr/bin/iccpd.sh -RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y -RUN rm -rf /debs +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/dockers/docker-iccpd/iccpd.j2 b/dockers/docker-iccpd/iccpd.j2 index 9fcb513d29a8..f5446eb6f54a 100644 --- a/dockers/docker-iccpd/iccpd.j2 +++ b/dockers/docker-iccpd/iccpd.j2 @@ -5,4 +5,5 @@ mclag_id:{{mclag_id}} peer_link:{{MC_LAG[mclag_id]['peer_link']}} mclag_interface:{{MC_LAG[mclag_id]['mclag_interface']}} {% endfor %} +system_mac:{{DEVICE_METADATA['localhost']['mac']}} diff --git a/src/iccpd/include/app_csm.h b/src/iccpd/include/app_csm.h index 6a5e554bc73e..a0565556d24c 100644 --- a/src/iccpd/include/app_csm.h +++ b/src/iccpd/include/app_csm.h @@ -1,25 +1,25 @@ /* -* app_csm.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * app_csm.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef APP_CSM_H_ #define APP_CSM_H_ @@ -30,7 +30,8 @@ struct CSM; -enum APP_CONNECTION_STATE { +enum APP_CONNECTION_STATE +{ APP_NONEXISTENT, APP_RESET, APP_CONNSENT, @@ -41,18 +42,19 @@ enum APP_CONNECTION_STATE { typedef enum APP_CONNECTION_STATE APP_CONNECTION_STATE_E; -struct AppCSM { +struct AppCSM +{ struct mLACP mlacp; APP_CONNECTION_STATE_E current_state; - + uint32_t rx_connect_msg_id; uint32_t tx_connect_msg_id; uint32_t invalid_msg_id; - + TAILQ_HEAD(app_msg_list, Msg) app_msg_list; - - uint8_t invalid_msg :1; - uint8_t nak_msg :1; + + uint8_t invalid_msg : 1; + uint8_t nak_msg : 1; }; void app_csm_init(struct CSM*, int all); diff --git a/src/iccpd/include/cmd_option.h b/src/iccpd/include/cmd_option.h index d81249ea5e93..ca5582cfcc60 100644 --- a/src/iccpd/include/cmd_option.h +++ b/src/iccpd/include/cmd_option.h @@ -1,25 +1,25 @@ /* -* cmd_option.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * cmd_option.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef CMD_OPTION_H_ #define CMD_OPTION_H_ @@ -35,40 +35,42 @@ #define MSG_LEN 81 #define CMD_OPTION_PARSER_INIT_VALUE \ -{ \ - .log_file_path = "/var/log/iccpd.log", \ - .pid_file_path = "/var/run/iccpd/iccpd.pid", \ - .cmd_file_path = "/var/run/iccpd/iccpd.vty", \ - .config_file_path = "/etc/iccpd/iccpd.conf", \ - .mclagdctl_file_path = "/var/run/iccpd/mclagdctl.sock", \ - .console_log = 0, \ - .telnet_port = 2015, \ - .init = cmd_option_parser_init, \ - .finalize = cmd_option_parser_finalize, \ - .dump_usage = cmd_option_parser_dump_usage, \ - .parse = cmd_option_parser_parse, \ -} + { \ + .log_file_path = "/var/log/iccpd.log", \ + .pid_file_path = "/var/run/iccpd/iccpd.pid", \ + .cmd_file_path = "/var/run/iccpd/iccpd.vty", \ + .config_file_path = "/etc/iccpd/iccpd.conf", \ + .mclagdctl_file_path = "/var/run/iccpd/mclagdctl.sock", \ + .console_log = 0, \ + .telnet_port = 2015, \ + .init = cmd_option_parser_init, \ + .finalize = cmd_option_parser_finalize, \ + .dump_usage = cmd_option_parser_dump_usage, \ + .parse = cmd_option_parser_parse, \ + } -struct CmdOption { - char* desc; - char* option; - char* parameter; - LIST_ENTRY(CmdOption) next; +struct CmdOption +{ + char* desc; + char* option; + char* parameter; + LIST_ENTRY(CmdOption) next; }; -struct CmdOptionParser { - char* log_file_path; - char* pid_file_path; - char* cmd_file_path; - char* config_file_path; - char *mclagdctl_file_path; - uint8_t console_log; - uint16_t telnet_port; - LIST_HEAD(option_list, CmdOption) option_list; - int (*parse)(struct CmdOptionParser*, int, char*[]); - void (*init)(struct CmdOptionParser*); - void (*finalize)(struct CmdOptionParser*); - void (*dump_usage)(struct CmdOptionParser*, char*); +struct CmdOptionParser +{ + char* log_file_path; + char* pid_file_path; + char* cmd_file_path; + char* config_file_path; + char *mclagdctl_file_path; + uint8_t console_log; + uint16_t telnet_port; + LIST_HEAD(option_list, CmdOption) option_list; + int (*parse)(struct CmdOptionParser*, int, char*[]); + void (*init)(struct CmdOptionParser*); + void (*finalize)(struct CmdOptionParser*); + void (*dump_usage)(struct CmdOptionParser*, char*); }; int cmd_option_parser_parse(struct CmdOptionParser*, int, char*[]); diff --git a/src/iccpd/include/iccp_cli.h b/src/iccpd/include/iccp_cli.h index 1c504ed12940..c85fc4316b5f 100644 --- a/src/iccpd/include/iccp_cli.h +++ b/src/iccpd/include/iccp_cli.h @@ -1,25 +1,25 @@ /* -* iccp_cli.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_cli.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef _ICCP_CLI_H #define _ICCP_CLI_H @@ -28,12 +28,14 @@ struct CSM; -typedef enum { +typedef enum +{ QU_TYPE_NONE, QU_TYPE_MLAG_ADD_PO } cli_queue_type_et; -typedef struct cli_param_queue { +typedef struct cli_param_queue +{ char ifname[16]; cli_queue_type_et type; int param; @@ -41,6 +43,13 @@ typedef struct cli_param_queue { LIST_ENTRY(cli_param_queue) cli_queue_next; } cli_param_queue_st; +#define MCLAG_ID_STR "mclag_id" +#define LOCAL_IP_STR "local_ip" +#define PEER_IP_STR "peer_ip" +#define PEER_LINK_STR "peer_link" +#define MCLAG_INTF_STR "mclag_interface" +#define SYSTEM_MAC_STR "system_mac" + int set_mc_lag_id(struct CSM* csm, uint16_t domain); int set_peer_link(int mid, const char* ifname); int set_local_address(int mid, const char* addr); @@ -52,4 +61,7 @@ int unset_peer_address(int mid); int iccp_cli_attach_mclag_domain_to_port_channel(int domain, const char* ifname); int iccp_cli_detach_mclag_domain_to_port_channel(const char* ifname); +int set_local_system_id(const char* mac); +int unset_local_system_id( ); + #endif diff --git a/src/iccpd/include/iccp_cmd.h b/src/iccpd/include/iccp_cmd.h index 80886e37d8d2..01f37456b71d 100644 --- a/src/iccpd/include/iccp_cmd.h +++ b/src/iccpd/include/iccp_cmd.h @@ -1,29 +1,29 @@ /* -* iccp_cmd.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_cmd.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef ICCP_CMD_H_ #define ICCP_CMD_H_ -int iccp_config_from_file (char *config_default_dir); +int iccp_config_from_file(char *config_default_dir); #endif /* ICCP_CMD_H_ */ diff --git a/src/iccpd/include/iccp_cmd_show.h b/src/iccpd/include/iccp_cmd_show.h index 4d3238f95a48..0fedca7cdddd 100644 --- a/src/iccpd/include/iccp_cmd_show.h +++ b/src/iccpd/include/iccp_cmd_show.h @@ -1,25 +1,25 @@ /* -* iccp_cmd_show.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_cmd_show.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef _ICCP_CMD_SHOW_H #define _ICCP_CMD_SHOW_H @@ -27,9 +27,9 @@ #define ICCP_MAX_PORT_NAME 20 #define ICCP_MAX_IP_STR_LEN 16 -extern int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) ; +extern int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id); extern int iccp_arp_dump(char * *buf, int *num, int mclag_id); extern int iccp_mac_dump(char * *buf, int *num, int mclag_id); -extern int iccp_local_if_dump(char * *buf, int *num,int mclag_id); +extern int iccp_local_if_dump(char * *buf, int *num, int mclag_id); extern int iccp_peer_if_dump(char * *buf, int *num, int mclag_id); #endif diff --git a/src/iccpd/include/iccp_consistency_check.h b/src/iccpd/include/iccp_consistency_check.h index e6fe51f364c5..6fa8ea47e2f4 100644 --- a/src/iccpd/include/iccp_consistency_check.h +++ b/src/iccpd/include/iccp_consistency_check.h @@ -1,32 +1,33 @@ /* -* iccp_consistency_check.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -* -*/ + * iccp_consistency_check.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + * + */ #ifndef _ICCP_CONSISTENCY_CHECK_H #define _ICCP_CONSISTENCY_CHECK_H -enum Reason_ID { +enum Reason_ID +{ REASON_NONE = 0, REASON_INTERRFACE_MODE_IS_ASYNC, REASON_PEER_IF_IP_IS_ASYNC, diff --git a/src/iccpd/include/iccp_csm.h b/src/iccpd/include/iccp_csm.h index 514252fe0c51..96a538bf2bb1 100644 --- a/src/iccpd/include/iccp_csm.h +++ b/src/iccpd/include/iccp_csm.h @@ -1,25 +1,25 @@ /* -* iccp_csm.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_csm.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef ICCP_CSM_H_ #define ICCP_CSM_H_ @@ -56,26 +56,29 @@ extern uint32_t ICCP_MSG_ID; /* Global Buffer */ extern char g_csm_buf[CSM_BUFFER_SIZE]; -struct IccpInfo { +struct IccpInfo +{ uint32_t icc_rg_id; char sender_name[MAX_L_ICC_SENDER_NAME]; uint32_t status_code; - uint8_t peer_capability_flag :1; - uint8_t peer_rg_connect_flag :1; - uint8_t sender_capability_flag :1; - uint8_t sender_rg_connect_flag :1; + uint8_t peer_capability_flag : 1; + uint8_t peer_rg_connect_flag : 1; + uint8_t sender_capability_flag : 1; + uint8_t sender_rg_connect_flag : 1; uint32_t rejected_msg_id; }; /* Receive message node */ -struct Msg { +struct Msg +{ char* buf; size_t len; TAILQ_ENTRY(Msg) tail; }; /* Connection state */ -enum ICCP_CONNECTION_STATE { +enum ICCP_CONNECTION_STATE +{ ICCP_NONEXISTENT, ICCP_INITIALIZED, ICCP_CAPSENT, @@ -86,16 +89,18 @@ enum ICCP_CONNECTION_STATE { typedef enum ICCP_CONNECTION_STATE ICCP_CONNECTION_STATE_E; -typedef enum stp_role_type_e { +typedef enum stp_role_type_e +{ STP_ROLE_NONE, /* mstp do nothing*/ STP_ROLE_ACTIVE, /* mstp report port state*/ STP_ROLE_STANDBY /* mstp fwd bpdu & set port state*/ } stp_role_type_et; /* Connection state machine instance */ -struct CSM { +struct CSM +{ int mlag_id; - + /* Socket info */ int sock_fd; pthread_mutex_t conn_mutex; @@ -107,31 +112,31 @@ struct CSM { char peer_ip[INET_ADDRSTRLEN]; char sender_ip[INET_ADDRSTRLEN]; void* sock_read_event_ptr; - + /* Msg queue */ TAILQ_HEAD(msg_list, Msg) msg_list; - + /* System ID */ time_t isolate_update_time; - + /* STP role */ stp_role_type_et role_type; - + /* Peers msg */ struct LocalInterface* peer_link_if; struct IccpInfo iccp_info; struct AppCSM app_csm; ICCP_CONNECTION_STATE_E current_state; - + /* Statistic info */ - uint64_t icc_msg_in_count; /* ICC message input count */ + uint64_t icc_msg_in_count; /* ICC message input count */ uint64_t icc_msg_out_count; /* ICC message Output count */ - uint64_t u_msg_in_count; /* Unknown message Input count */ - uint64_t i_msg_in_count; /* Illegal message Input count */ - + uint64_t u_msg_in_count; /* Unknown message Input count */ + uint64_t i_msg_in_count; /* Illegal message Input count */ + /* Log */ struct MsgLog msg_log; - + LIST_ENTRY(CSM) next; LIST_HEAD(csm_if_list, If_info) if_bind_list; }; diff --git a/src/iccpd/include/iccp_ifm.h b/src/iccpd/include/iccp_ifm.h index 7929e30f200e..4f99d4cea336 100644 --- a/src/iccpd/include/iccp_ifm.h +++ b/src/iccpd/include/iccp_ifm.h @@ -1,25 +1,25 @@ /* -* iccp_ifm.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_ifm.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef ICCP_IFM_H #define ICCP_IFM_H @@ -30,12 +30,12 @@ int iccp_sys_local_if_list_get_init(); int iccp_arp_get_init(); -void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]); +void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]); -int do_one_neigh_request (struct nlmsghdr *n); +int do_one_neigh_request(struct nlmsghdr *n); void iccp_from_netlink_port_state_handler( char * ifname, int state); - void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n); +void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n); #endif // LACP_IFM_H diff --git a/src/iccpd/include/iccp_netlink.h b/src/iccpd/include/iccp_netlink.h index 8defb999138b..26ce050b4e48 100644 --- a/src/iccpd/include/iccp_netlink.h +++ b/src/iccpd/include/iccp_netlink.h @@ -1,22 +1,22 @@ /* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef ICCP_NETLINK_H #define ICCP_NETLINK_H diff --git a/src/iccpd/include/logger.h b/src/iccpd/include/logger.h index 6a9b64f05112..8d4502e8a75e 100644 --- a/src/iccpd/include/logger.h +++ b/src/iccpd/include/logger.h @@ -1,25 +1,25 @@ /* -* logger.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * logger.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef LOGGER_H_ #define LOGGER_H_ @@ -31,29 +31,30 @@ typedef enum _iccpd_log_level_t { - DEBUG_LOG_LEVEL = 0, - INFO_LOG_LEVEL = 1, - NOTICE_LOG_LEVEL = 2, - WARN_LOG_LEVEL = 3, - ERR_LOG_LEVEL = 4, - CRITICAL_LOG_LEVEL = 5 + DEBUG_LOG_LEVEL = 0, + INFO_LOG_LEVEL = 1, + NOTICE_LOG_LEVEL = 2, + WARN_LOG_LEVEL = 3, + ERR_LOG_LEVEL = 4, + CRITICAL_LOG_LEVEL = 5 } _iccpd_log_level_t; #define LOGBUF_SIZE 1024 #define ICCPD_UTILS_SYSLOG (syslog) -#define ICCPD_LOG_CRITICAL(tag, format, args...) write_log(CRITICAL_LOG_LEVEL, tag, format, ##args) -#define ICCPD_LOG_ERR(tag, format, args...) write_log(ERR_LOG_LEVEL, tag, format, ##args) -#define ICCPD_LOG_WARN(tag, format, args...) write_log(WARN_LOG_LEVEL, tag, format, ##args) -#define ICCPD_LOG_NOTICE(tag, format, args...) write_log(NOTICE_LOG_LEVEL, tag, format, ##args) -#define ICCPD_LOG_INFO(tag, format, args...) write_log(INFO_LOG_LEVEL, tag, format, ##args) -#define ICCPD_LOG_DEBUG(tag, format, args...) write_log(DEBUG_LOG_LEVEL, tag, format, ##args) +#define ICCPD_LOG_CRITICAL(tag, format, args ...) write_log(CRITICAL_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_ERR(tag, format, args ...) write_log(ERR_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_WARN(tag, format, args ...) write_log(WARN_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_NOTICE(tag, format, args ...) write_log(NOTICE_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_INFO(tag, format, args ...) write_log(INFO_LOG_LEVEL, tag, format, ## args) +#define ICCPD_LOG_DEBUG(tag, format, args ...) write_log(DEBUG_LOG_LEVEL, tag, format, ## args) -struct LoggerConfig { - uint8_t console_log_enabled; - uint8_t log_level; - uint8_t init; +struct LoggerConfig +{ + uint8_t console_log_enabled; + uint8_t log_level; + uint8_t init; }; struct LoggerConfig* logger_get_configuration(); diff --git a/src/iccpd/include/mlacp_fsm.h b/src/iccpd/include/mlacp_fsm.h index b89d21b780a1..6442d9ff560d 100644 --- a/src/iccpd/include/mlacp_fsm.h +++ b/src/iccpd/include/mlacp_fsm.h @@ -1,26 +1,26 @@ /* -* mlacp_fsm.h -* mLACP finite state machine handler. -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * mlacp_fsm.h + * mLACP finite state machine handler. + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef _MLACP_FSM_H #define _MLACP_FSM_H @@ -33,7 +33,8 @@ struct CSM; -enum MLACP_APP_STATE { +enum MLACP_APP_STATE +{ MLACP_STATE_INIT, MLACP_STATE_STAGE1, MLACP_STATE_STAGE2, @@ -44,7 +45,8 @@ enum MLACP_APP_STATE { typedef enum MLACP_APP_STATE MLACP_APP_STATE_E; /* for sender only*/ -enum MLACP_SYNC_STATE { +enum MLACP_SYNC_STATE +{ MLACP_SYNC_SYSCONF=0, MLACP_SYNC_AGGCONF, MLACP_SYNC_AGGSTATE, @@ -56,26 +58,28 @@ enum MLACP_SYNC_STATE { typedef enum MLACP_SYNC_STATE MLACP_SYNC_STATE_E; -struct Remote_System { +struct Remote_System +{ uint8_t system_id[ETHER_ADDR_LEN]; uint16_t system_priority; uint32_t node_id; }; -struct mLACP { +struct mLACP +{ int id; int sync_req_num; - + MLACP_APP_STATE_E current_state; MLACP_SYNC_STATE_E sync_state; - + uint8_t wait_for_sync_data; uint8_t need_to_sync; uint8_t node_id; uint8_t system_id[ETHER_ADDR_LEN]; uint16_t system_priority; uint8_t system_config_changed; - + struct Remote_System remote_system; const char* error_msg; TAILQ_HEAD(mlacp_msg_list, Msg) mlacp_msg_list; @@ -83,7 +87,7 @@ struct mLACP { TAILQ_HEAD(arp_info_list, Msg) arp_list; TAILQ_HEAD(mac_msg_list, Msg) mac_msg_list; TAILQ_HEAD(mac_info_list, Msg) mac_list; - + LIST_HEAD(lif_list, LocalInterface) lif_list; LIST_HEAD(lif_purge_list, LocalInterface) lif_purge_list; LIST_HEAD(pif_list, PeerInterface) pif_list; diff --git a/src/iccpd/include/mlacp_link_handler.h b/src/iccpd/include/mlacp_link_handler.h index 60e5671877fd..55892d1861c8 100644 --- a/src/iccpd/include/mlacp_link_handler.h +++ b/src/iccpd/include/mlacp_link_handler.h @@ -1,24 +1,24 @@ /* -* mlacp_link_handler.h -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * mlacp_link_handler.h + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef __MLACP_LINK_HANDLER__ #define __MLACP_LINK_HANDLER__ @@ -27,9 +27,9 @@ #include "../include/mlacp_tlv.h" /***************************************** - * Link Handler - * - * ***************************************/ +* Link Handler +* +* ***************************************/ void mlacp_portchannel_state_handler(struct CSM* csm, struct LocalInterface* local_if, int po_state); void mlacp_peer_conn_handler(struct CSM* csm); void mlacp_peer_disconn_handler(struct CSM* csm); @@ -39,9 +39,9 @@ void update_stp_peer_link(struct CSM *csm, struct PeerInterface *peer_if, int po void update_peerlink_isolate_from_pif(struct CSM *csm, struct PeerInterface *pif, int po_state, int new_create); void mlacp_mlag_link_add_handler(struct CSM *csm, struct LocalInterface *lif); void mlacp_mlag_link_del_handler(struct CSM *csm, struct LocalInterface *lif); -void set_peerlink_mlag_port_learn (struct LocalInterface *lif, int enable); +void set_peerlink_mlag_port_learn(struct LocalInterface *lif, int enable); void peerlink_port_isolate_cleanup(struct CSM* csm); -void update_peerlink_isolate_from_all_csm_lif (struct CSM* csm); +void update_peerlink_isolate_from_all_csm_lif(struct CSM* csm); int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac); int mlacp_fsm_arp_del(char *ifname, uint32_t ip); diff --git a/src/iccpd/include/mlacp_sync_prepare.h b/src/iccpd/include/mlacp_sync_prepare.h index 0b78763052b5..ec480be324dc 100644 --- a/src/iccpd/include/mlacp_sync_prepare.h +++ b/src/iccpd/include/mlacp_sync_prepare.h @@ -1,53 +1,53 @@ /* -* mlacp_sync_prepare.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * mlacp_sync_prepare.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef __MLACP_SYNC_PREPARE__ #define __MLACP_SYNC_PREPARE__ struct CSM; /***************************************** - * Tool Function - * - * ***************************************/ - void update_system_id(struct CSM* csm); +* Tool Function +* +* ***************************************/ +void update_system_id(struct CSM* csm); /***************************************** - * LACP Sync - * - * ***************************************/ +* LACP Sync +* +* ***************************************/ int mlacp_sync_with_kernel_callback(); /***************************************** - * MLACP Sync - * - * ***************************************/ +* MLACP Sync +* +* ***************************************/ int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_buf_size); int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end); -int mlacp_prepare_for_sys_config(struct CSM* csm,char* buf, size_t max_buf_size); +int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size); int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg); int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg); -int mlacp_prepare_for_heartbeat(struct CSM* csm,char* buf, size_t max_buf_size); -int mlacp_prepare_for_Aggport_state(struct CSM* csm,char* buf, size_t max_buf_size, struct LocalInterface* local_if); +int mlacp_prepare_for_heartbeat(struct CSM* csm, char* buf, size_t max_buf_size); +int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* local_if); int mlacp_prepare_for_Aggport_config(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* lif, int purge_flag); int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* port_channel); int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* peerlink_port); diff --git a/src/iccpd/include/mlacp_sync_update.h b/src/iccpd/include/mlacp_sync_update.h index 7e09360fbd6c..d42abe216af6 100644 --- a/src/iccpd/include/mlacp_sync_update.h +++ b/src/iccpd/include/mlacp_sync_update.h @@ -1,25 +1,25 @@ /* -* -* mlacp_sync_update.h -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * + * mlacp_sync_update.h + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef __MLACP_SYNC_UPDATE__ #define __MLACP_SYNC_UPDATE__ @@ -28,9 +28,9 @@ #include "mlacp_tlv.h" /***************************************** - * FSM Sync Update API - * - * ***************************************/ +* FSM Sync Update API +* +* ***************************************/ int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV* tlv); int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv); diff --git a/src/iccpd/include/mlacp_tlv.h b/src/iccpd/include/mlacp_tlv.h index 480390bcec7a..947a491a3846 100644 --- a/src/iccpd/include/mlacp_tlv.h +++ b/src/iccpd/include/mlacp_tlv.h @@ -1,25 +1,25 @@ /* -* mlacp_tlv.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * mlacp_tlv.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef MLACP_TLV_H_ #define MLACP_TLV_H_ @@ -34,82 +34,85 @@ #define MLACP_SYSCONF_NODEID_FREE_MASK 0x0F /* -* RFC 7275 -* 7.2.3. mLACP System Config TLV -* [Page 51] -*/ -struct mLACPSysConfigTLV { + * RFC 7275 + * 7.2.3. mLACP System Config TLV + * [Page 51] + */ +struct mLACPSysConfigTLV +{ ICCParameter icc_parameter; /* [IEEE-802.1AX], Section 5.3.2. */ uint8_t sys_id[ETHER_ADDR_LEN]; /* [IEEE-802.1AX], Section 5.3.2. */ uint16_t sys_priority; /* - * RFC 7275 - * 7.2.3. mLACP System Config TLV - * [Page 51] - */ + * RFC 7275 + * 7.2.3. mLACP System Config TLV + * [Page 51] + */ uint8_t node_id; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPSysConfigTLV mLACPSysConfigTLV; /* -* RFC 7275 -* 7.2.4. mLACP Aggregator Config TLV -* [Page 52] -* NOTE: In this project, Aggregator configuration and state TLV is not support. -*/ -struct mLACPAggConfigTLV { + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 52] + * NOTE: In this project, Aggregator configuration and state TLV is not support. + */ +struct mLACPAggConfigTLV +{ ICCParameter icc_parameter; /* - * RFC 7275 - * 7.2.4. mLACP Aggregator Config TLV - * [Page 53] - */ + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ uint8_t ro_id[8]; /* [IEEE-802.1AX], Section 5.4.6. */ uint16_t agg_id; /* - * RFC 7275 - * 7.2.4. mLACP Aggregator Config TLV - * [Page 53] - */ + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ uint8_t mac_addr[ETHER_ADDR_LEN]; /* [IEEE-802.1AX], Section 5.3.5. */ uint16_t actor_key; /* - * RFC 7275 - * 7.2.4. mLACP Aggregator Config TLV - * [Page 53] - */ + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 53] + */ uint16_t member_ports_priority; uint8_t flags; /* - * RFC 7275 - * 7.2.4. mLACP Aggregator Config TLV - * [Page 54] - */ + * RFC 7275 + * 7.2.4. mLACP Aggregator Config TLV + * [Page 54] + */ uint8_t agg_name_len; char agg_name[MAX_L_PORT_NAME]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPAggConfigTLV mLACPAggConfigTLV; /* -* RFC 7275 -* 7.2.4. mLACP Port Config TLV -* [Page 54] -*/ -struct mLACPPortConfigTLV { + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 54] + */ +struct mLACPPortConfigTLV +{ ICCParameter icc_parameter; /* [IEEE-802.1AX], Section 5.3.4. */ uint16_t port_num; /* - * RFC 7275 - * 7.2.5. mLACP Port Config TLV - * [Page 55] - */ + * RFC 7275 + * 7.2.5. mLACP Port Config TLV + * [Page 55] + */ uint8_t mac_addr[ETHER_ADDR_LEN]; /* [IEEE-802.1AX], Section 5.3.5. */ uint16_t actor_key; @@ -118,16 +121,16 @@ struct mLACPPortConfigTLV { /* IF-MIB [RFC2863] */ uint32_t port_speed; /* - * RFC 7275 - * 7.2.4. mLACP Port Config TLV - * [Page 55] - */ + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 55] + */ uint8_t flags; /* - * RFC 7275 - * 7.2.4. mLACP Port Config TLV - * [Page 56] - */ + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 56] + */ uint8_t port_name_len; /* IF-MIB [RFC2863] */ char port_name[MAX_L_PORT_NAME]; @@ -135,22 +138,23 @@ struct mLACPPortConfigTLV { /* NOS */ uint8_t orphan; uint8_t l3_mode; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPPortConfigTLV mLACPPortConfigTLV; /* -* RFC 7275 -* 7.2.6. mLACP Port Priority TLV -* [Page 56] -*/ -struct mLACPPortPriorityTLV { + * RFC 7275 + * 7.2.6. mLACP Port Priority TLV + * [Page 56] + */ +struct mLACPPortPriorityTLV +{ ICCParameter icc_parameter; /* - * RFC 7275 - * 7.2.6. mLACP Port Priority TLV - * [Page 57] - */ + * RFC 7275 + * 7.2.6. mLACP Port Priority TLV + * [Page 57] + */ uint16_t op_code; /* [IEEE-802.1AX], Section 5.3.4. */ uint16_t port_num; @@ -159,16 +163,17 @@ struct mLACPPortPriorityTLV { /* [IEEE-802.1AX], Section 5.3.4. */ uint16_t last_port_priority; uint16_t current_port_priority; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPPortPriorityTLV mLACPPortPriorityTLV; /* -* RFC 7275 -* 7.2.7. mLACP Port State TLV -* [Page 58] -*/ -struct mLACPPortStateTLV { + * RFC 7275 + * 7.2.7. mLACP Port State TLV + * [Page 58] + */ +struct mLACPPortStateTLV +{ ICCParameter icc_parameter; /* [IEEE-802.1AX], Section 5.4.2.2, item r. */ uint8_t partner_sys_id[ETHER_ADDR_LEN]; @@ -191,10 +196,10 @@ struct mLACPPortStateTLV { /* [IEEE-802.1AX], Section 5.4.8 */ uint8_t selected; /* - * RFC 7275 - * 7.2.7. mLACP Port State TLV - * [Page 60] - */ + * RFC 7275 + * 7.2.7. mLACP Port State TLV + * [Page 60] + */ uint8_t port_state; /* [IEEE-802.1AX], Section 5.4.6. */ uint16_t agg_id; @@ -204,17 +209,18 @@ struct mLACPPortStateTLV { uint16_t port_id; uint8_t l3_mode; uint8_t is_peer_link; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPPortStateTLV mLACPPortStateTLV; /* -* RFC 7275 -* 7.2.8. mLACP Aggregator State TLV -* [Page 60] -* NOTE: In this project, Aggregator configuration and state TLV is not support. -*/ -struct mLACPAggPortStateTLV { + * RFC 7275 + * 7.2.8. mLACP Aggregator State TLV + * [Page 60] + * NOTE: In this project, Aggregator configuration and state TLV is not support. + */ +struct mLACPAggPortStateTLV +{ ICCParameter icc_parameter; /* [IEEE-802.1AX], Section 5.4.2.2, item r. */ uint8_t partner_sys_id[ETHER_ADDR_LEN]; @@ -227,173 +233,185 @@ struct mLACPAggPortStateTLV { /* [IEEE-802.1AX], Section 5.3.5. */ uint16_t actor_key; /* - * RFC 7275 - * 7.2.8. mLACP Aggregator State TLV - * [Page 61] - */ + * RFC 7275 + * 7.2.8. mLACP Aggregator State TLV + * [Page 61] + */ uint8_t agg_state; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPAggPortStateTLV mLACPAggPortStateTLV; /* -* RFC 7275 -* 7.2.9. mLACP Synchronization Request TLV -* [Page 61] -*/ -struct mLACPSyncReqTLV { + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 61] + */ +struct mLACPSyncReqTLV +{ ICCParameter icc_parameter; /* - * RFC 7275 - * 7.2.9. mLACP Synchronization Request TLV - * [Page 62] - */ + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 62] + */ uint16_t req_num; #if __BYTE_ORDER == __BIG_ENDIAN - uint16_t c_bit :1; + uint16_t c_bit : 1; /* - * RFC 7275 - * 7.2.9. mLACP Synchronization Request TLV - * [Page 63] - */ - uint16_t s_bit :1; - uint16_t req_type :14; + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 63] + */ + uint16_t s_bit : 1; + uint16_t req_type : 14; #elif __BYTE_ORDER == __LITTLE_ENDIAN - uint16_t req_type :14; + uint16_t req_type : 14; /* - * RFC 7275 - * 7.2.9. mLACP Synchronization Request TLV - * [Page 63] - */ - uint16_t s_bit :1; - uint16_t c_bit :1; + * RFC 7275 + * 7.2.9. mLACP Synchronization Request TLV + * [Page 63] + */ + uint16_t s_bit : 1; + uint16_t c_bit : 1; #endif /* [IEEE-802.1AX], Section 5.3.4. */ /* [IEEE-802.1AX], Section 5.4.6. */ uint16_t port_num_agg_id; /* [IEEE-802.1AX], Section 5.3.5. */ uint16_t actor_key; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPSyncReqTLV mLACPSyncReqTLV; /* -* RFC 7275 -* 7.2.10. mLACP Synchronization Data TLV -* [Page 63] -*/ -struct mLACPSyncDataTLV { + * RFC 7275 + * 7.2.10. mLACP Synchronization Data TLV + * [Page 63] + */ +struct mLACPSyncDataTLV +{ ICCParameter icc_parameter; /* - * RFC 7275 - * 7.2.10. mLACP Synchronization Data TLV - * [Page 64] - */ + * RFC 7275 + * 7.2.10. mLACP Synchronization Data TLV + * [Page 64] + */ uint16_t req_num; uint16_t flags; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPSyncDataTLV mLACPSyncDataTLV; /* VLAN Information TLV*/ -struct mLACPVLANData { +struct mLACPVLANData +{ uint16_t vlan_id; -}__attribute__ ((packed)); +} __attribute__ ((packed)); /* -* Port Channel Information TLV -*/ -struct mLACPPortChannelInfoTLV { + * Port Channel Information TLV + */ +struct mLACPPortChannelInfoTLV +{ ICCParameter icc_parameter; uint16_t agg_id; char if_name[MAX_L_PORT_NAME]; uint8_t if_name_len; - uint8_t l3_mode; + uint8_t l3_mode; uint32_t ipv4_addr; uint16_t orphan; uint16_t po_id; uint16_t num_of_vlan_id; struct mLACPVLANData vlanData[0]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPPortChannelInfoTLV mLACPPortChannelInfoTLV; /* -* Port PeerLink Information TLV -*/ -struct mLACPPeerLinkInfoTLV { + * Port PeerLink Information TLV + */ +struct mLACPPeerLinkInfoTLV +{ ICCParameter icc_parameter; char if_name[MAX_L_PORT_NAME]; uint8_t port_type; -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct mLACPPeerLinkInfoTLV mLACPPeerLinkInfoTLV; - -struct mLACPVLANInfoTLV { +struct mLACPVLANInfoTLV +{ ICCParameter icc_parameter; uint16_t id; /* Local Interface ID, not VLAN ID */ uint16_t num_of_vlan_id; struct mLACPVLANData vlanData[0]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); /* -* MAC Information TLV -*/ -struct mLACPMACInfoTLV { + * MAC Information TLV + */ +struct mLACPMACInfoTLV +{ ICCParameter icc_parameter; uint8_t type;/*add or del*/ char mac_str[32]; uint16_t vid; /*Current if name that set in chip*/ char ifname[MAX_L_PORT_NAME]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); /* -* ARP Information TLV -*/ -struct mLACPARPInfoTLV { + * ARP Information TLV + */ +struct mLACPARPInfoTLV +{ ICCParameter icc_parameter; /* Local Interface ID */ uint8_t type; char ifname[MAX_L_PORT_NAME]; uint32_t ipv4_addr; uint8_t mac_addr[ETHER_ADDR_LEN]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); /* -* NOS: STP Information TLV -*/ + * NOS: STP Information TLV + */ struct stp_msg_s; -struct mLACPSTPInfoTLV { +struct mLACPSTPInfoTLV +{ ICCParameter icc_parameter; uint8_t stp_msg[0]; -}__attribute__ ((packed)); +} __attribute__ ((packed)); /* -* NOS: Heartbeat -*/ -struct mLACPHeartbeatTLV { + * NOS: Heartbeat + */ +struct mLACPHeartbeatTLV +{ ICCParameter icc_parameter; uint8_t heartbeat; -}__attribute__ ((packed)); +} __attribute__ ((packed)); /* -* NOS: Warm_reboot -*/ -struct mLACPWarmbootTLV { + * NOS: Warm_reboot + */ +struct mLACPWarmbootTLV +{ ICCParameter icc_parameter; uint8_t warmboot; -}__attribute__ ((packed)); +} __attribute__ ((packed)); -enum ARP_OP_TYPE { +enum ARP_OP_TYPE +{ ARP_SYNC_LIF, ARP_SYNC_ADD, ARP_SYNC_DEL, }; -struct ARPMsg { +struct ARPMsg +{ uint8_t op_type; char ifname[MAX_L_PORT_NAME]; uint32_t ipv4_addr; @@ -401,31 +419,35 @@ struct ARPMsg { time_t update_time; }; -enum MAC_AGE_TYPE { - MAC_AGE_LOCAL = 1,/*MAC in local switch is ageout*/ - MAC_AGE_PEER = 2, /*MAC in peer switch is ageout*/ +enum MAC_AGE_TYPE +{ + MAC_AGE_LOCAL = 1, /*MAC in local switch is ageout*/ + MAC_AGE_PEER = 2, /*MAC in peer switch is ageout*/ }; -enum MAC_OP_TYPE { - MAC_SYNC_ADD = 1, - MAC_SYNC_DEL = 2, - MAC_SYNC_ACK = 4, +enum MAC_OP_TYPE +{ + MAC_SYNC_ADD = 1, + MAC_SYNC_DEL = 2, + MAC_SYNC_ACK = 4, }; -enum MAC_TYPE { - MAC_TYPE_STATIC = 1, - MAC_TYPE_DYNAMIC = 2, +enum MAC_TYPE +{ + MAC_TYPE_STATIC = 1, + MAC_TYPE_DYNAMIC = 2, }; -struct MACMsg { - uint8_t op_type;/*add or del*/ - uint8_t fdb_type;/*static or dynamic*/ +struct MACMsg +{ + uint8_t op_type; /*add or del*/ + uint8_t fdb_type; /*static or dynamic*/ char mac_str[32]; uint16_t vid; /*Current if name that set in chip*/ char ifname[MAX_L_PORT_NAME]; - /*if we set the mac to peer-link, origin_ifname store the - original if name that learned from chip*/ + /*if we set the mac to peer-link, origin_ifname store the + original if name that learned from chip*/ char origin_ifname[MAX_L_PORT_NAME]; uint8_t age_flag;/*local or peer is age?*/ }; diff --git a/src/iccpd/include/msg_format.h b/src/iccpd/include/msg_format.h index 4b7a091ffa0b..3f2458d07325 100644 --- a/src/iccpd/include/msg_format.h +++ b/src/iccpd/include/msg_format.h @@ -1,25 +1,25 @@ /* -* msg_format.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * msg_format.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef MSG_FORMAT_H_ #define MSG_FORMAT_H_ @@ -80,11 +80,11 @@ #define TLV_T_MLACP_CONNECT 0x0030 #define TLV_T_MLACP_DISCONNECT 0x0031 #define TLV_T_MLACP_SYSTEM_CONFIG 0x0032 -#define TLV_T_MLACP_PORT_CONFIG 0x0033//no support -#define TLV_T_MLACP_PORT_PRIORITY 0x0034//no support -#define TLV_T_MLACP_PORT_STATE 0x0035//no support -#define TLV_T_MLACP_AGGREGATOR_CONFIG 0x0036 -#define TLV_T_MLACP_AGGREGATOR_STATE 0x0037 +#define TLV_T_MLACP_PORT_CONFIG 0x0033 //no support +#define TLV_T_MLACP_PORT_PRIORITY 0x0034 //no support +#define TLV_T_MLACP_PORT_STATE 0x0035 //no support +#define TLV_T_MLACP_AGGREGATOR_CONFIG 0x0036 +#define TLV_T_MLACP_AGGREGATOR_STATE 0x0037 #define TLV_T_MLACP_SYNC_REQUEST 0x0038 #define TLV_T_MLACP_SYNC_DATA 0x0039 #define TLV_T_MLACP_HEARTBEAT 0x003A @@ -103,59 +103,82 @@ /* Debug */ static char* get_tlv_type_string(int type) { - switch(type) + switch (type) { case TLV_T_ICCP_CAPABILITY: return "TLV_T_ICCP_CAPABILITY"; + case TLV_T_ICC_SENDER_NAME: return "TLV_T_ICC_SENDER_NAME"; + case TLV_T_NAK: return "TLV_T_NAK"; + case TLV_T_REQUESTED_PROTOCOL_VER: return "TLV_T_REQUESTED_PROTOCOL_VER"; + case TLV_T_DISCONNECT_CODE: return "TLV_T_DISCONNECT_CODE"; + case TLV_T_ICC_RG_ID: return "TLV_T_ICC_RG_ID"; + case TLV_T_MLACP_CONNECT: return "TLV_T_MLACP_CONNECT"; + case TLV_T_MLACP_DISCONNECT: return "TLV_T_MLACP_DISCONNECT"; + case TLV_T_MLACP_SYSTEM_CONFIG: return "TLV_T_MLACP_SYSTEM_CONFIG"; + case TLV_T_MLACP_PORT_CONFIG: return "TLV_T_MLACP_PORT_CONFIG"; + case TLV_T_MLACP_PORT_PRIORITY: return "TLV_T_MLACP_PORT_PRIORITY"; + case TLV_T_MLACP_PORT_STATE: return "TLV_T_MLACP_PORT_STATE"; + case TLV_T_MLACP_AGGREGATOR_CONFIG: return "TLV_T_MLACP_AGGREGATOR_CONFIG"; + case TLV_T_MLACP_AGGREGATOR_STATE: return "TLV_T_MLACP_AGGREGATOR_STATE"; + case TLV_T_MLACP_SYNC_REQUEST: return "TLV_T_MLACP_SYNC_REQUEST"; + case TLV_T_MLACP_SYNC_DATA: return "TLV_T_MLACP_SYNC_DATA"; + case TLV_T_MLACP_HEARTBEAT: return "TLV_T_MLACP_HEARTBEAT"; + case TLV_T_MLACP_DISCONNECT_CAUSE: return "TLV_T_MLACP_DISCONNECT_CAUSE"; /* NOS Feature */ case TLV_T_MLACP_ORPHAN_PORT: return "TLV_T_MLACP_ORPHAN_PORT"; + case TLV_T_MLACP_PORT_CHANNEL_INFO: return "TLV_T_MLACP_PORT_CHANNEL_INFO"; + case TLV_T_MLACP_PEERLINK_INFO: return "TLV_T_MLACP_PEERLINK_INFO"; + case TLV_T_MLACP_ARP_INFO: return "TLV_T_MLACP_ARP_INFO"; + case TLV_T_MLACP_MAC_INFO: return "TLV_T_MLACP_MAC_INFO"; + case TLV_T_MLACP_STP_INFO: return "TLV_T_MLACP_STP_INFO"; } + return "UNKNOWN"; } @@ -178,27 +201,36 @@ static char* get_tlv_type_string(int type) /* Debug */ static char* get_status_string(int status) { - switch(status) + switch (status) { case STATUS_CODE_U_ICCP_RG: return "Unknown ICCP RG"; + case STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED: return "ICCP Connection Count Exceeded"; + case STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED: return "ICCP Application Connection Count Exceede"; + case STATUS_CODE_ICCP_APP_NOT_IN_RG: return "ICCP Application not in RG"; + case STATUS_CODE_INCOMPATIBLE_ICCP_PROTOCOL_VER: return "Incompatible ICCP Protocol Version"; + case STATUS_CODE_ICCP_REJECTED_MSG: return "ICCP Rejected Message"; + case STATUS_CODE_ICCP_ADMINISTRATIVELY_DISABLED: return "ICCP Administratively Disabled"; + case STATUS_CODE_ICCP_RG_REMOVED: return "ICCP RG Removed"; + case STATUS_CODE_ICCP_APP_REMOVED_FROM_RG: return "ICCP Application Removed from RG"; } + return "UNKNOWN"; } /* @@ -206,17 +238,18 @@ static char* get_status_string(int status) * 3.5. LDP Messages * [Page 44] */ -struct LDPHdr { +struct LDPHdr +{ #if __BYTE_ORDER == __BIG_ENDIAN - uint16_t u_bit :1; - uint16_t msg_type :15; + uint16_t u_bit : 1; + uint16_t msg_type : 15; #elif __BYTE_ORDER == __LITTLE_ENDIAN - uint16_t msg_type :15; - uint16_t u_bit :1; + uint16_t msg_type : 15; + uint16_t u_bit : 1; #endif - uint16_t msg_len; - uint32_t msg_id; -}__attribute__ ((packed)); + uint16_t msg_len; + uint32_t msg_id; +} __attribute__ ((packed)); typedef struct LDPHdr LDPHdr; @@ -225,18 +258,20 @@ typedef struct LDPHdr LDPHdr; * 6.1.1. ICC Header * [Page 24] */ -struct ICCRGIDTLV { - uint16_t type; - uint16_t len; - uint32_t icc_rg_id; -}__attribute__ ((packed)); +struct ICCRGIDTLV +{ + uint16_t type; + uint16_t len; + uint32_t icc_rg_id; +} __attribute__ ((packed)); typedef struct ICCRGIDTLV ICCRGIDTLV; -struct ICCHdr { - LDPHdr ldp_hdr; - ICCRGIDTLV icc_rg_id_tlv; -}__attribute__ ((packed)); +struct ICCHdr +{ + LDPHdr ldp_hdr; + ICCRGIDTLV icc_rg_id_tlv; +} __attribute__ ((packed)); typedef struct ICCHdr ICCHdr; @@ -245,18 +280,19 @@ typedef struct ICCHdr ICCHdr; * 6.1.2. ICC Parameter Encoding * [Page 26] */ -struct ICCParameter { +struct ICCParameter +{ #if __BYTE_ORDER == __BIG_ENDIAN - uint16_t u_bit :1; - uint16_t f_bit :1; - uint16_t type :14; + uint16_t u_bit : 1; + uint16_t f_bit : 1; + uint16_t type : 14; #elif __BYTE_ORDER == __LITTLE_ENDIAN - uint16_t type :14; - uint16_t f_bit :1; - uint16_t u_bit :1; + uint16_t type : 14; + uint16_t f_bit : 1; + uint16_t u_bit : 1; #endif - uint16_t len; -}__attribute__ ((packed)); + uint16_t len; +} __attribute__ ((packed)); typedef struct ICCParameter ICCParameter; @@ -265,10 +301,11 @@ typedef struct ICCParameter ICCParameter; * 6.2.1. ICC Sender Name TLV * [Page 28] */ -struct ICCSenderNameTLV { - ICCParameter icc_parameter; - char sender_name[MAX_L_ICC_SENDER_NAME]; -}__attribute__ ((packed)); +struct ICCSenderNameTLV +{ + ICCParameter icc_parameter; + char sender_name[MAX_L_ICC_SENDER_NAME]; +} __attribute__ ((packed)); typedef struct ICCSenderNameTLV ICCSenderNameTLV; @@ -277,10 +314,11 @@ typedef struct ICCSenderNameTLV ICCSenderNameTLV; * 6.3. RG Disconnect Message * [Page 29] */ -struct DisconnectCodeTLV { - ICCParameter icc_parameter; - uint32_t iccp_status_code; -}__attribute__ ((packed)); +struct DisconnectCodeTLV +{ + ICCParameter icc_parameter; + uint32_t iccp_status_code; +} __attribute__ ((packed)); typedef struct DisconnectCodeTLV DisconnectCodeTLV; @@ -289,11 +327,12 @@ typedef struct DisconnectCodeTLV DisconnectCodeTLV; * 6.4.1. Notification Message TLVs * [Page 32] */ -struct NAKTLV { - ICCParameter icc_parameter; - uint32_t iccp_status_code; - uint32_t rejected_msg_id; -}__attribute__ ((packed)); +struct NAKTLV +{ + ICCParameter icc_parameter; + uint32_t iccp_status_code; + uint32_t rejected_msg_id; +} __attribute__ ((packed)); typedef struct NAKTLV NAKTLV; @@ -302,11 +341,12 @@ typedef struct NAKTLV NAKTLV; * 6.4.1. Notification Message TLVs * [Page 34] */ -struct RequestedProtocolVerTLV { - ICCParameter icc_parameter; - uint16_t connection_ref; - uint16_t requested_ver; -}__attribute__ ((packed)); +struct RequestedProtocolVerTLV +{ + ICCParameter icc_parameter; + uint16_t connection_ref; + uint16_t requested_ver; +} __attribute__ ((packed)); typedef struct RequestedProtocolVerTLV RequestedProtocolVerTLV; @@ -315,18 +355,19 @@ typedef struct RequestedProtocolVerTLV RequestedProtocolVerTLV; * 8. LDP Capability Negotiation * [Page 65] */ -struct LDPICCPCapabilityTLV { - ICCParameter icc_parameter; +struct LDPICCPCapabilityTLV +{ + ICCParameter icc_parameter; #if __BYTE_ORDER == __BIG_ENDIAN - uint16_t s_bit :1; - uint16_t reserved :15; + uint16_t s_bit : 1; + uint16_t reserved : 15; #elif __BYTE_ORDER == __LITTLE_ENDIAN - uint16_t reserved :15; - uint16_t s_bit :1; + uint16_t reserved : 15; + uint16_t s_bit : 1; #endif - uint8_t major_ver; - uint8_t minior_ver; -}__attribute__ ((packed)); + uint8_t major_ver; + uint8_t minior_ver; +} __attribute__ ((packed)); typedef struct LDPICCPCapabilityTLV LDPICCPCapabilityTLV; @@ -335,20 +376,21 @@ typedef struct LDPICCPCapabilityTLV LDPICCPCapabilityTLV; * 7.2.1. mLACP Connect TLV * [Page 47] */ -struct AppConnectTLV { +struct AppConnectTLV +{ ICCParameter icc_parameter; uint16_t protocol_version; #if __BYTE_ORDER == __BIG_ENDIAN - uint16_t a_bit :1; - uint16_t reserved :15; + uint16_t a_bit : 1; + uint16_t reserved : 15; #elif __BYTE_ORDER == __LITTLE_ENDIAN - uint16_t reserved :15; - uint16_t a_bit :1; + uint16_t reserved : 15; + uint16_t a_bit : 1; #endif /* Optional Sub-TLVs */ /* No optional sub-TLVs in this version */ -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct AppConnectTLV AppConnectTLV; @@ -357,12 +399,13 @@ typedef struct AppConnectTLV AppConnectTLV; * 7.2.2. mLACP Disconnect TLV * [Page 48] */ -struct AppDisconnectTLV { +struct AppDisconnectTLV +{ ICCParameter icc_parameter; /* Optional Sub-TLVs */ /* mLACP Disconnect Cause TLV */ -}__attribute__ ((packed)); +} __attribute__ ((packed)); typedef struct AppDisconnectTLV AppDisconnectTLV; @@ -371,56 +414,62 @@ typedef struct AppDisconnectTLV AppDisconnectTLV; * 7.2.2.1. mLACP Disconnect Cause TLV * [Page 49] */ -struct AppDisconnectCauseTLV { +struct AppDisconnectCauseTLV +{ ICCParameter iccp_parameter; /* Disconnect Cause String */ char cause_string[0]; /* Trick */ -}__attribute__ ((packed)); +} __attribute__ ((packed)); /*syncd send msg type to iccpd*/ -typedef enum mclag_syncd_msg_type_e_ { - MCLAG_SYNCD_MSG_TYPE_NONE = 0, - MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1 +typedef enum mclag_syncd_msg_type_e_ +{ + MCLAG_SYNCD_MSG_TYPE_NONE = 0, + MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1 }mclag_syncd_msg_type_e; -typedef enum mclag_msg_type_e_ { - MCLAG_MSG_TYPE_NONE = 0, - MCLAG_MSG_TYPE_PORT_ISOLATE = 1, - MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE = 2, - MCLAG_MSG_TYPE_FLUSH_FDB = 3, - MCLAG_MSG_TYPE_SET_MAC = 4, - MCLAG_MSG_TYPE_SET_FDB = 5, - MCLAG_MSG_TYPE_GET_FDB_CHANGES = 20 +typedef enum mclag_msg_type_e_ +{ + MCLAG_MSG_TYPE_NONE = 0, + MCLAG_MSG_TYPE_PORT_ISOLATE = 1, + MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE = 2, + MCLAG_MSG_TYPE_FLUSH_FDB = 3, + MCLAG_MSG_TYPE_SET_MAC = 4, + MCLAG_MSG_TYPE_SET_FDB = 5, + MCLAG_MSG_TYPE_GET_FDB_CHANGES = 20 }mclag_msg_type_e; -typedef enum mclag_sub_option_type_e_ { - MCLAG_SUB_OPTION_TYPE_NONE = 0, - MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC = 1, - MCLAG_SUB_OPTION_TYPE_ISOLATE_DST = 2, - MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE = 3, - MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4, - MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC = 5, - MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6 +typedef enum mclag_sub_option_type_e_ +{ + MCLAG_SUB_OPTION_TYPE_NONE = 0, + MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC = 1, + MCLAG_SUB_OPTION_TYPE_ISOLATE_DST = 2, + MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE = 3, + MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4, + MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC = 5, + MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6 } mclag_sub_option_type_e; -struct IccpSyncdHDr { - uint8_t ver; - uint8_t type; - uint16_t len; +struct IccpSyncdHDr +{ + uint8_t ver; + uint8_t type; + uint16_t len; }; -typedef struct mclag_sub_option_hdr_t_ { - - uint8_t op_type; +typedef struct mclag_sub_option_hdr_t_ +{ + + uint8_t op_type; - /* - * Length of option value, not including the header. - */ - uint16_t op_len; - uint8_t data[]; + /* + * Length of option value, not including the header. + */ + uint16_t op_len; + uint8_t data[]; }mclag_sub_option_hdr_t; struct mclag_fdb_info @@ -428,19 +477,21 @@ struct mclag_fdb_info char mac[32]; unsigned int vid; char port_name[32]; - short type;/*dynamic or static*/ - short op_type;/*add or del*/ -}; + short type; /*dynamic or static*/ + short op_type; /*add or del*/ +}; /* For storing message log: For Notification TLV */ -struct MsgTypeSet { +struct MsgTypeSet +{ uint32_t msg_id; uint16_t type; uint16_t tlv; }; -struct MsgLog { +struct MsgLog +{ struct MsgTypeSet msg[MAX_MSG_LOG_SIZE]; uint32_t end_index; }; diff --git a/src/iccpd/include/port.h b/src/iccpd/include/port.h index c82de73cfeb4..91bdc9966209 100644 --- a/src/iccpd/include/port.h +++ b/src/iccpd/include/port.h @@ -1,25 +1,25 @@ /* -* port.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * port.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef PORT_H_ #define PORT_H_ @@ -30,10 +30,10 @@ #define ETHER_ADDR_LEN 6 /* -* RFC 7275 -* 7.2.4. mLACP Port Config TLV -* [Page 56] -*/ + * RFC 7275 + * 7.2.4. mLACP Port Config TLV + * [Page 56] + */ #define MAX_L_PORT_NAME 20 /* defined in RFC 7275 - 7.2.7 (p.59) */ @@ -49,70 +49,75 @@ #define IF_T_VLAN 2 #define IF_T_VXLAN 3 #define IF_T_BRIDGE 4 -typedef struct { +typedef struct +{ char *ifname; int type; } itf_type_t; -struct If_info{ +struct If_info +{ char name[MAX_L_PORT_NAME]; - LIST_ENTRY(If_info) csm_next; + LIST_ENTRY(If_info) csm_next; }; -struct VLAN_ID { +struct VLAN_ID +{ uint16_t vid; uint16_t vlan_removed; struct LocalInterface* vlan_itf; /* loacl vlan interface */ LIST_ENTRY(VLAN_ID) port_next; }; -struct PeerInterface { +struct PeerInterface +{ int ifindex; int type; char name[MAX_L_PORT_NAME]; - + uint8_t mac_addr[ETHER_ADDR_LEN]; uint8_t state; uint32_t ipv4_addr; - + uint8_t l3_mode; uint8_t is_peer_link; int po_id; uint8_t po_active; - + struct CSM* csm; - + LIST_ENTRY(PeerInterface) mlacp_next; LIST_HEAD(peer_vlan_list, VLAN_ID) vlan_list; }; -struct LocalInterface { +struct LocalInterface +{ int ifindex; int type; char name[MAX_L_PORT_NAME]; - + uint8_t mac_addr[ETHER_ADDR_LEN]; uint8_t mac_addr_ori[ETHER_ADDR_LEN]; uint8_t state; uint32_t ipv4_addr; uint8_t prefixlen; - + uint8_t l3_mode; uint8_t is_peer_link; char portchannel_member_buf[512]; uint8_t is_arp_accept; - int po_id; /* Port Channel ID */ - uint8_t po_active; /* Port Channel is in active status? */ - int mlacp_state; /* Record mlacp state */ + int po_id; /* Port Channel ID */ + uint8_t po_active; /* Port Channel is in active status? */ + int mlacp_state; /* Record mlacp state */ uint8_t isolate_to_peer_link; - + struct CSM* csm; - + uint8_t changed; uint8_t port_config_sync; - + LIST_HEAD(local_vlan_list, VLAN_ID) vlan_list; - + LIST_ENTRY(LocalInterface) system_next; LIST_ENTRY(LocalInterface) system_purge_next; LIST_ENTRY(LocalInterface) mlacp_next; diff --git a/src/iccpd/include/scheduler.h b/src/iccpd/include/scheduler.h index d791434d1760..b3be274282c8 100644 --- a/src/iccpd/include/scheduler.h +++ b/src/iccpd/include/scheduler.h @@ -1,25 +1,25 @@ /* -* scheduler.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * scheduler.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef SCHEDULER_H_ #define SCHEDULER_H_ @@ -51,7 +51,7 @@ void scheduler_finalize(); void scheduler_loop(); void scheduler_start(); void scheduler_server_sock_init(); -int scheduler_csm_read_callback(struct CSM* csm) ; +int scheduler_csm_read_callback(struct CSM* csm); int iccp_get_server_sock_fd(); int scheduler_server_accept(); int iccp_receive_signal_handler(struct System* sys); diff --git a/src/iccpd/include/system.h b/src/iccpd/include/system.h index 4608eb936e6e..1205fe55f9ad 100644 --- a/src/iccpd/include/system.h +++ b/src/iccpd/include/system.h @@ -1,25 +1,25 @@ /* -* system.h -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * system.h + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #ifndef SYSTEM_H_ #define SYSTEM_H_ @@ -40,7 +40,7 @@ #define FRONT_PANEL_PORT_PREFIX "Ethernet" #define PORTCHANNEL_PREFIX "PortChannel" #define VLAN_PREFIX "Vlan" -#define VXLAN_TUNNEL_PREFIX "VTTNL" +#define VXLAN_TUNNEL_PREFIX "VTTNL" #define WARM_REBOOT 1 @@ -50,7 +50,8 @@ struct CSM; #define MAX_BUFSIZE 4096 #endif -struct System { +struct System +{ int server_fd;/* Peer-Link Socket*/ int sync_fd; int sync_ctrl_fd; @@ -69,24 +70,24 @@ struct System { int sig_pipe_w; int warmboot_start; int warmboot_exit; - + /* Info List*/ LIST_HEAD(csm_list, CSM) csm_list; LIST_HEAD(lif_all_list, LocalInterface) lif_list; LIST_HEAD(lif_purge_all_list, LocalInterface) lif_purge_list; - + /* Settings */ char* log_file_path; char* cmd_file_path; char* config_file_path; - char* mclagdctl_file_path; + char* mclagdctl_file_path; int pid_file_fd; int telnet_port; fd_set readfd; /*record socket need to listen*/ int readfd_count; time_t csm_trans_time; int need_sync_team_again; - int need_sync_netlink_again; + int need_sync_netlink_again; }; struct CSM* system_create_csm(); diff --git a/src/iccpd/src/app_csm.c b/src/iccpd/src/app_csm.c index 26475a05c109..7d8f8c550d89 100644 --- a/src/iccpd/src/app_csm.c +++ b/src/iccpd/src/app_csm.c @@ -1,24 +1,24 @@ /* -* app_csm.c -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * app_csm.c + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -35,15 +35,15 @@ * * ***************************************/ #define APP_CSM_QUEUE_REINIT(list) \ - {\ - struct Msg* msg = NULL;\ - while (!TAILQ_EMPTY(&(list))) {\ - msg = TAILQ_FIRST(&(list));\ - TAILQ_REMOVE(&(list), msg, tail);\ - free(msg->buf);\ - free(msg);\ - }\ - TAILQ_INIT(&(list));\ + { \ + struct Msg* msg = NULL; \ + while (!TAILQ_EMPTY(&(list))) { \ + msg = TAILQ_FIRST(&(list)); \ + TAILQ_REMOVE(&(list), msg, tail); \ + free(msg->buf); \ + free(msg); \ + } \ + TAILQ_INIT(&(list)); \ } /* Application State Machine instance initialization */ @@ -54,7 +54,7 @@ void app_csm_init(struct CSM* csm, int all) APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); - if(all) + if (all) { bzero(&(csm->app_csm), sizeof(struct AppCSM)); APP_CSM_QUEUE_REINIT(csm->app_csm.app_msg_list); @@ -89,7 +89,7 @@ void app_csm_transit(struct CSM* csm) return; } - if(csm->app_csm.current_state != APP_OPERATIONAL && csm->current_state == ICCP_OPERATIONAL) + if (csm->app_csm.current_state != APP_OPERATIONAL && csm->current_state == ICCP_OPERATIONAL) { csm->app_csm.current_state = APP_OPERATIONAL; } @@ -115,30 +115,31 @@ void app_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) if (msg == NULL ) return; - icc_hdr = (ICCHdr*) msg->buf; - param = (ICCParameter*) &msg->buf[sizeof(struct ICCHdr)]; + icc_hdr = (ICCHdr*)msg->buf; + param = (ICCParameter*)&msg->buf[sizeof(struct ICCHdr)]; *(uint16_t *)param = ntohs(*(uint16_t *)param); if ( icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) { - if(param->type > TLV_T_MLACP_CONNECT && param->type < TLV_T_MLACP_LIST_END) + if (param->type > TLV_T_MLACP_CONNECT && param->type < TLV_T_MLACP_LIST_END) mlacp_enqueue_msg(csm, msg); else TAILQ_INSERT_TAIL(&(csm->app_csm.app_msg_list), msg, tail); } else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) { - naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; - for(i=0; ibuf[sizeof(ICCHdr)]; + + for (i = 0; i < MAX_MSG_LOG_SIZE; ++i) { - if(ntohl(naktlv->rejected_msg_id) == csm->msg_log.msg[i].msg_id) + if (ntohl(naktlv->rejected_msg_id) == csm->msg_log.msg[i].msg_id) { tlv = csm->msg_log.msg[i].tlv; break; } } - if(tlv > TLV_T_MLACP_CONNECT && tlv <= TLV_T_MLACP_MAC_INFO) + if (tlv > TLV_T_MLACP_CONNECT && tlv <= TLV_T_MLACP_MAC_INFO) mlacp_enqueue_msg(csm, msg); else TAILQ_INSERT_TAIL(&(csm->app_csm.app_msg_list), msg, tail); @@ -167,8 +168,8 @@ struct Msg* app_csm_dequeue_msg(struct CSM* csm) /* APP NAK message handle function */ int app_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) { - ICCHdr* icc_hdr = (ICCHdr*) buf; - NAKTLV* naktlv = (NAKTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + NAKTLV* naktlv = (NAKTLV*)&buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); ICCPD_LOG_DEBUG(__FUNCTION__, " Response NAK"); @@ -201,8 +202,7 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) return 0; /* remove purge from the csm*/ - do - { + do { LIST_FOREACH(lifp, &(MLACP(csm).lif_purge_list), mlacp_purge_next) { if (lifp == lif) @@ -226,7 +226,8 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) /* join new csm*/ LIST_INSERT_HEAD(&(MLACP(csm).lif_list), lif, mlacp_next); lif->csm = csm; - if (lif->type == IF_T_PORT_CHANNEL) lif->port_config_sync = 1; + if (lif->type == IF_T_PORT_CHANNEL) + lif->port_config_sync = 1; ICCPD_LOG_INFO(__FUNCTION__, "%s: MLACP bind on csm %p", lif->name, csm); if (lif->type == IF_T_PORT_CHANNEL) @@ -289,7 +290,7 @@ int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname) struct LocalInterface *lif_po = NULL; sys = system_get_instance(); - if(sys == NULL) + if (sys == NULL) return 0; if (csm == NULL) diff --git a/src/iccpd/src/cmd_option.c b/src/iccpd/src/cmd_option.c index aaef80924d19..596dafb73711 100644 --- a/src/iccpd/src/cmd_option.c +++ b/src/iccpd/src/cmd_option.c @@ -1,25 +1,25 @@ /* -* cmd_option.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * cmd_option.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include "../include/cmd_option.h" @@ -28,12 +28,12 @@ struct CmdOption* cmd_option_find(struct CmdOptionParser* parser, char* opt_name struct CmdOption* opt = NULL; if (opt_name == NULL) - return NULL; + return NULL; LIST_FOREACH(opt, &(parser->option_list), next) { - if (strcmp(opt->option, opt_name) == 0) - return opt; + if (strcmp(opt->option, opt_name) == 0) + return opt; } return NULL; @@ -59,20 +59,20 @@ struct CmdOption* cmd_option_add(struct CmdOptionParser* parser, char* opt_name) struct CmdOption* opt = NULL; if (opt_name == NULL) - return NULL; + return NULL; if ((opt = cmd_option_find(parser, opt_name)) != NULL) - return opt; + return opt; - if ((opt = (struct CmdOption*) malloc(sizeof(struct CmdOption))) == NULL) + if ((opt = (struct CmdOption*)malloc(sizeof(struct CmdOption))) == NULL) { - strerror(errno); + strerror(errno); } else { - opt->option = opt_name; - opt->parameter = NULL; - opt->desc = NULL; - LIST_INSERT_HEAD(&(parser->option_list), opt, next); + opt->option = opt_name; + opt->parameter = NULL; + opt->desc = NULL; + LIST_INSERT_HEAD(&(parser->option_list), opt, next); } return opt; @@ -113,8 +113,8 @@ static void cmd_option_register(struct CmdOptionParser* parser, char* syntax, ch return; -failed: - if(opt_name) + failed: + if (opt_name) free(opt_name); if (desc_copy != NULL) free(desc_copy); @@ -127,7 +127,7 @@ static void cmd_option_register(struct CmdOptionParser* parser, char* syntax, ch void cmd_option_parser_init(struct CmdOptionParser* parser) { if (parser == NULL) - return; + return; LIST_INIT(&parser->option_list); cmd_option_register(parser, "-l ", "Set log file path.\n(Default: /var/log/iccpd.log)"); @@ -168,25 +168,28 @@ void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_nam else snprintf(buf, MSG_LEN - 1, "%s", opt->option); fprintf(stdout, "%24s ", buf); + while (index < strlen(opt->desc)) { while (index < strlen(opt->desc) - && opt->desc[index] != '\n' && length < 49) + && opt->desc[index] != '\n' && length < 49) { ++index; ++length; } + memset(buf, 0, MSG_LEN); strncpy(buf, &(opt->desc[begin]), length); if (length == 49 && index < strlen(opt->desc) - && opt->desc[index] != '\n' - && opt->desc[index - 1] != ' ' - && opt->desc[index] != ' ') + && opt->desc[index] != '\n' + && opt->desc[index - 1] != ' ' + && opt->desc[index] != ' ') { buf[length] = '-'; buf[length + 1] = '\0'; } - if (length < 49) ++index; + if (length < 49) + ++index; begin = index; length = 0; if (first_line != 0) @@ -197,6 +200,7 @@ void cmd_option_parser_dump_usage(struct CmdOptionParser* parser, char* prog_nam else fprintf(stdout, "%28c%-52s\n", ' ', buf); } + fflush(stdout); } } @@ -210,7 +214,7 @@ int cmd_option_parser_parse(struct CmdOptionParser* parser, int argc, char* argv int num = 0; if (parser == NULL) - return -255; + return -255; while (index < argc) { diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c index f95a127ed007..6c020a2a500a 100644 --- a/src/iccpd/src/iccp_cli.c +++ b/src/iccpd/src/iccp_cli.c @@ -1,25 +1,25 @@ /* -* iccp_cli.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_cli.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include @@ -30,16 +30,17 @@ #include "../include/mlacp_link_handler.h" #include "../include/iccp_netlink.h" /* -* 'id <1-65535>' command -*/ + * 'id <1-65535>' command + */ int set_mc_lag_id( struct CSM *csm, uint16_t id) { - if (!csm) return -1; + if (!csm) + return -1; ICCPD_LOG_INFO(__FUNCTION__, "Set mlag-id : %d", id); /* Mlag-ID, RG-ID, MLACP-ID - Temporary let the three id be the same*/ + Temporary let the three id be the same*/ csm->mlag_id = id; csm->iccp_info.icc_rg_id = id; csm->app_csm.mlacp.id = id; @@ -48,7 +49,8 @@ int set_mc_lag_id( struct CSM *csm, uint16_t id) int unset_mc_lag_id( struct CSM *csm, uint16_t id) { - if (!csm) return -1; + if (!csm) + return -1; /* Mlag-ID, RG-ID, MLACP-ID*/ csm->mlag_id = 0; @@ -61,8 +63,8 @@ int unset_mc_lag_id( struct CSM *csm, uint16_t id) } /* -* 'peer-link WORD' command -*/ + * 'peer-link WORD' command + */ int set_peer_link(int mid, const char* ifname) { struct CSM* csm = NULL; @@ -78,13 +80,15 @@ int set_peer_link(int mid, const char* ifname) } csm = system_get_csm_by_mlacp_id(mid); - if(csm == NULL) return -1; + if (csm == NULL) + return -1; - if (len > IFNAMSIZ) return -1; + if (len > IFNAMSIZ) + return -1; if (strlen(csm->peer_itf_name) > 0) { - if(strcmp(csm->peer_itf_name, ifname) == 0) + if (strcmp(csm->peer_itf_name, ifname) == 0) { ICCPD_LOG_INFO(__FUNCTION__, "Peer-link not be changed"); return 0; @@ -92,11 +96,11 @@ int set_peer_link(int mid, const char* ifname) else { ICCPD_LOG_INFO(__FUNCTION__, "Change peer-link : %s -> %s", - csm->peer_itf_name, ifname); + csm->peer_itf_name, ifname); scheduler_session_disconnect_handler(csm); - if(csm->peer_link_if) + if (csm->peer_link_if) { csm->peer_link_if->is_peer_link = 0; csm->peer_link_if = NULL; @@ -106,7 +110,7 @@ int set_peer_link(int mid, const char* ifname) else { ICCPD_LOG_INFO(__FUNCTION__, "Set mlag %d peer-link : %s", - csm->mlag_id,ifname); + csm->mlag_id, ifname); } memset(csm->peer_itf_name, 0, IFNAMSIZ); @@ -120,7 +124,7 @@ int set_peer_link(int mid, const char* ifname) lif->is_peer_link = 1; MLACP(csm).system_config_changed = 1; - if(lif->type == IF_T_PORT_CHANNEL) + if (lif->type == IF_T_PORT_CHANNEL) iccp_get_port_member_list(lif); } @@ -132,9 +136,10 @@ int unset_peer_link(int mid) struct CSM* csm = NULL; csm = system_get_csm_by_mlacp_id(mid); - if(csm == NULL) return -1; + if (csm == NULL) + return -1; - if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /*must be enabled mac learn*/ set_peerlink_mlag_port_learn(csm->peer_link_if, 1); @@ -148,7 +153,7 @@ int unset_peer_link(int mid) /* clean peer-link*/ memset(csm->peer_itf_name, 0, IFNAMSIZ); - if(csm->peer_link_if) + if (csm->peer_link_if) { csm->peer_link_if->is_peer_link = 0; csm->peer_link_if = NULL; @@ -159,29 +164,35 @@ int unset_peer_link(int mid) } /* -* 'local ip address A.B.C.D' command -*/ + * 'local ip address A.B.C.D' command + */ int set_local_address(int mid, const char* addr) { struct CSM* csm = NULL; size_t len = 0; csm = system_get_csm_by_mlacp_id(mid); - if(csm == NULL) return -1; - if (addr == NULL) return -1; + if (csm == NULL) + return -1; + if (addr == NULL) + return -1; - if (strlen(csm->sender_ip) > 0) { - if (strcmp(csm->sender_ip, addr) == 0) { + if (strlen(csm->sender_ip) > 0) + { + if (strcmp(csm->sender_ip, addr) == 0) + { ICCPD_LOG_INFO(__FUNCTION__, "Local-address not be changed"); return 0; } - else { + else + { ICCPD_LOG_INFO(__FUNCTION__, "Change local-address : %s -> %s", - csm->sender_ip, addr); + csm->sender_ip, addr); scheduler_session_disconnect_handler(csm); } } - else { + else + { ICCPD_LOG_INFO(__FUNCTION__, "Set local-address : %s", addr); } @@ -199,7 +210,8 @@ int unset_local_address(int mid) struct CSM* csm = NULL; csm = system_get_csm_by_mlacp_id(mid); - if(csm == NULL) return -1; + if (csm == NULL) + return -1; memset(csm->sender_ip, 0, INET_ADDRSTRLEN); memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); @@ -211,22 +223,24 @@ int unset_local_address(int mid) } /* -* 'peer-address A.B.C.D' command -*/ + * 'peer-address A.B.C.D' command + */ int set_peer_address(int mid, const char* addr) { struct CSM* csm = NULL; size_t len = 0; csm = system_get_csm_by_mlacp_id(mid); - if(csm == NULL) return -1; - if(addr == NULL) return -1; + if (csm == NULL) + return -1; + if (addr == NULL) + return -1; len = strlen(addr); if (strlen(csm->peer_ip) > 0) { - if(strcmp(csm->peer_ip, addr) == 0) + if (strcmp(csm->peer_ip, addr) == 0) { ICCPD_LOG_INFO(__FUNCTION__, "Peer-address not be changed"); return 0; @@ -234,7 +248,7 @@ int set_peer_address(int mid, const char* addr) else { ICCPD_LOG_INFO(__FUNCTION__, "Change peer-address : %s -> %s", - csm->peer_ip, addr); + csm->peer_ip, addr); scheduler_session_disconnect_handler(csm); } } @@ -254,7 +268,8 @@ int unset_peer_address(int mid) struct CSM* csm = NULL; csm = system_get_csm_by_mlacp_id(mid); - if(csm == NULL) return -1; + if (csm == NULL) + return -1; memset(csm->peer_ip, 0, INET_ADDRSTRLEN); @@ -273,14 +288,16 @@ int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname if (!ifname) return -1; - if(strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX))!=0) { + if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0) + { ICCPD_LOG_DEBUG(__FUNCTION__, "attach interface(%s) is not a port-channel", ifname); return -1; } csm = system_get_csm_by_mlacp_id(domain); - if (csm == NULL) { + if (csm == NULL) + { ICCPD_LOG_DEBUG(__FUNCTION__, "MC-LAG ID %d doesn't exist", domain); return -1; } @@ -288,20 +305,20 @@ int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname lif = local_if_find_by_name(ifname); if (lif) { - mlacp_bind_port_channel_to_csm(csm, ifname); + mlacp_bind_port_channel_to_csm(csm, ifname); } LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) { - if (strcmp(cif->name,ifname) ==0) - break; + if (strcmp(cif->name, ifname) == 0) + break; } - if(cif == NULL) + if (cif == NULL) { - cif = (struct If_info *) malloc(sizeof(struct If_info)); + cif = (struct If_info *)malloc(sizeof(struct If_info)); if (!cif) - return -1; + return -1; snprintf(cif->name, MAX_L_PORT_NAME, "%s", ifname); LIST_INSERT_HEAD(&(csm->if_bind_list), cif, csm_next); @@ -321,7 +338,8 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) if (!ifname) return -1; - if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX))!=0) { + if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0) + { ICCPD_LOG_DEBUG(__FUNCTION__, "detach interface(%s) is not a port-channel", ifname); return -1; @@ -330,7 +348,7 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) /* find po*/ if (!(lif_po = local_if_find_by_name(ifname)) || lif_po->type != IF_T_PORT_CHANNEL - || lif_po->po_id <=0 + || lif_po->po_id <= 0 || lif_po->csm == NULL) { return -1; @@ -355,8 +373,131 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) { - if (strcmp(ifname, cif->name) ==0) - LIST_REMOVE(cif, csm_next); + if (strcmp(ifname, cif->name) == 0) + LIST_REMOVE(cif, csm_next); + } + return 0; +} + +/* This function parses a string to a binary mac address (uint8_t[6]) + The string should contain mac address only. No spaces are allowed. + The mac address separators could be either ':' or '-'*/ +int parseMacString(const char * str_mac, uint8_t* bin_mac) +{ + if (bin_mac == NULL) + { + return -1; + } + + /* 6 hexadecimal numbers (two digits each) + 5 delimiters*/ + if (strlen(str_mac) != ETHER_ADDR_LEN * 2 + 5) + { + return -1; + } + + /* first check that all mac address separators are equal to each other + 2, 5, 8, 11, and 14 are MAC address separator positions*/ + if (!(str_mac[2] == str_mac[5] + && str_mac[5] == str_mac[8] + && str_mac[8] == str_mac[11] + && str_mac[11] == str_mac[14])) + { + return -1; + } + + /* then check that the first separator is equal to ':' or '-'*/ + if (str_mac[2] != ':' && str_mac[2] != '-') + { + return -1; + } + + for (int i = 0; i < ETHER_ADDR_LEN; ++i) + { + int left = i * 3; /* left digit position of hexadecimal number*/ + int right = left + 1; /* right digit position of hexadecimal number*/ + + if (str_mac[left] >= '0' && str_mac[left] <= '9') + { + bin_mac[i] = (uint8_t)(str_mac[left] - '0'); + } + else if (str_mac[left] >= 'A' && str_mac[left] <= 'F') + { + bin_mac[i] = (uint8_t)(str_mac[left] - 'A' + 0x0a); + } + else if (str_mac[left] >= 'a' && str_mac[left] <= 'f') + { + bin_mac[i] = (uint8_t)(str_mac[left] - 'a' + 0x0a); + } + else + { + return -1; + } + + bin_mac[i] = (uint8_t)(bin_mac[i] << 4); + + if (str_mac[right] >= '0' && str_mac[right] <= '9') + { + bin_mac[i] |= (uint8_t)(str_mac[right] - '0'); + } + else if (str_mac[right] >= 'A' && str_mac[right] <= 'F') + { + bin_mac[i] |= (uint8_t)(str_mac[right] - 'A' + 0x0a); + } + else if (str_mac[right] >= 'a' && str_mac[right] <= 'f') + { + bin_mac[i] |= (uint8_t)(str_mac[right] - 'a' + 0x0a); + } + else + { + return -1; + } + } + + return 0; +} + +int set_local_system_id(const char* mac) +{ + struct System* sys = NULL; + struct CSM* csm = NULL; + char syscmd[128]; + int ret = 0; + + if ((sys = system_get_instance()) == NULL ) + return 0; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + parseMacString(mac, MLACP(csm).system_id); + + ICCPD_LOG_DEBUG(__FUNCTION__, " Set local systemID [%02X:%02X:%02X:%02X:%02X:%02X].", + MLACP(csm).system_id[0], MLACP(csm).system_id[1], MLACP(csm).system_id[2], + MLACP(csm).system_id[3], MLACP(csm).system_id[4], MLACP(csm).system_id[5]); + } + + /*When changing the mac of a vlan member port, the mac of Bridge will be changed.*/ + /*The Bridge mac can not be the same as peer system id, so fix the Bridge MAC address here.*/ + sprintf(syscmd, "ip link set dev Bridge address %s > /dev/null 2>&1", mac); + ret = system(syscmd); + ICCPD_LOG_DEBUG(__FUNCTION__, " %s ret = %d", syscmd, ret); + + return 0; +} + +int unset_local_system_id( ) +{ + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + struct System* sys = NULL; + struct CSM* csm = NULL; + + if ((sys = system_get_instance()) == NULL ) + return 0; + + LIST_FOREACH(csm, &(sys->csm_list), next) + { + memcpy(MLACP(csm).system_id, null_mac, ETHER_ADDR_LEN); } + return 0; } + diff --git a/src/iccpd/src/iccp_cmd.c b/src/iccpd/src/iccp_cmd.c index 847b24ae956e..fc9082bf042b 100644 --- a/src/iccpd/src/iccp_cmd.c +++ b/src/iccpd/src/iccp_cmd.c @@ -1,25 +1,25 @@ /* -* iccp_cmd.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_cmd.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -71,7 +71,7 @@ int iccp_config_from_command(char * line) cp = line; /* Skip white spaces. */ - while (isspace ((int) *cp) && *cp != '\0') + while (isspace((int)*cp) && *cp != '\0') cp++; /* Return if there is only white spaces */ @@ -80,56 +80,63 @@ int iccp_config_from_command(char * line) end = cp; - /* Skip end white spaces. */ - while (!isspace ((int) *end) && *end != '\0') + /* Skip end white spaces. */ + while (!isspace((int)*end) && *end != '\0') end++; *end = '\0'; /*mc-lag id*/ - if (strncmp(cp,"mclag_id:",9) == 0 ) + if (strncmp(cp, MCLAG_ID_STR, strlen(MCLAG_ID_STR)) == 0 ) { - cp += 9; + cp += strlen(MCLAG_ID_STR) + 1; mid = atoi(cp); set_mc_lag_by_id(mid); } - else if (strncmp(cp,"local_ip:",9) == 0) /*local ip*/ + else if (strncmp(cp, LOCAL_IP_STR, strlen(LOCAL_IP_STR)) == 0) /*local ip*/ { - cp += 9; - set_local_address(mid,cp); + cp += strlen(LOCAL_IP_STR) + 1; + set_local_address(mid, cp); } - else if (strncmp(cp,"peer_ip:",8) == 0) /*peer ip*/ + else if (strncmp(cp, PEER_IP_STR, strlen(PEER_IP_STR)) == 0) /*peer ip*/ { - cp += 8; - set_peer_address(mid,cp); + cp += strlen(PEER_IP_STR) + 1; + set_peer_address(mid, cp); } - else if(strncmp(cp,"peer_link:",10) == 0) + else if (strncmp(cp, PEER_LINK_STR, strlen(PEER_LINK_STR)) == 0)/*peer link*/ { - cp += 10; - set_peer_link(mid,cp); + cp += strlen(PEER_LINK_STR) + 1; + set_peer_link(mid, cp); } - else if(strncmp(cp,"mclag_interface:",16) == 0) + else if (strncmp(cp, MCLAG_INTF_STR, strlen(MCLAG_INTF_STR)) == 0)/*mclag interface*/ { - cp += 10; + cp += strlen(MCLAG_INTF_STR) + 1; while (1) { start = cp; + while (!(*cp == ',' || *cp == '\r' || *cp == '\n') && - *cp != '\0') + *cp != '\0') cp++; + slen = cp - start; - strncpy (token, start, slen); + strncpy(token, start, slen); *(token + slen) = '\0'; iccp_cli_attach_mclag_domain_to_port_channel(mid, token); - while ((isspace ((int) *cp) || *cp == '\n' || *cp == '\r' || *cp == ',') && - *cp != '\0') + while ((isspace((int)*cp) || *cp == '\n' || *cp == '\r' || *cp == ',') && + *cp != '\0') cp++; if (*cp == '\0') break; } } + else if (strncmp(cp, SYSTEM_MAC_STR, strlen(SYSTEM_MAC_STR)) == 0)/*system mac*/ + { + cp += strlen(SYSTEM_MAC_STR) + 1; + set_local_system_id(cp); + } else { /*error*/ @@ -140,19 +147,20 @@ int iccp_config_from_command(char * line) /* Configration make from file. */ int -iccp_config_from_file (char *config_default_dir) +iccp_config_from_file(char *config_default_dir) { FILE *confp = NULL; char command_buf[CONFIG_LINE_LEN]; - confp = fopen (config_default_dir, "r"); + confp = fopen(config_default_dir, "r"); if (confp == NULL) return (1); - while (fgets (command_buf, CONFIG_LINE_LEN, confp)) + while (fgets(command_buf, CONFIG_LINE_LEN, confp)) { iccp_config_from_command(command_buf); } + fclose(confp); return 0; diff --git a/src/iccpd/src/iccp_cmd_show.c b/src/iccpd/src/iccp_cmd_show.c index 8b0e874d8662..70aaaf98b6bf 100644 --- a/src/iccpd/src/iccp_cmd_show.c +++ b/src/iccpd/src/iccp_cmd_show.c @@ -1,25 +1,25 @@ /* -* iccp_cmd_show.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_cmd_show.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include #include @@ -40,10 +40,10 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) struct CSM *csm = NULL; struct LocalInterface *peer_link_if = NULL; struct LocalInterface *lif_po = NULL; - char unknown[] = {"Unknown"}; - int mclag_num= 0; + char unknown[] = { "Unknown" }; + int mclag_num = 0; int id_exist = 0; - int str_size =0; + int str_size = 0; int len = 0; char *state_buf = NULL; int state_buf_size = MCLAGDCTL_CMD_SIZE; @@ -67,7 +67,7 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) else state_info.keepalive = 0; - if (mclag_id >0) + if (mclag_id > 0) { if (csm->mlag_id == mclag_id) id_exist = 1; @@ -78,9 +78,9 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) peer_link_if = local_if_find_by_name(csm->peer_itf_name); if (csm->mlag_id <= 0) - state_info.mclag_id = -1; + state_info.mclag_id = -1; else - state_info.mclag_id = csm->mlag_id; + state_info.mclag_id = csm->mlag_id; memcpy(state_info.local_ip, csm->sender_ip, ICCP_MAX_IP_STR_LEN); memcpy(state_info.peer_ip, csm->peer_ip, ICCP_MAX_IP_STR_LEN); @@ -100,8 +100,8 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) { - if (str_size -len < ICCP_MAX_PORT_NAME) - break; + if (str_size - len < ICCP_MAX_PORT_NAME) + break; if (lif_po->type == IF_T_PORT_CHANNEL) len += snprintf(state_info.enabled_po + len, str_size - len, "%s,", lif_po->name); @@ -109,16 +109,16 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) /*Skip the last ','*/ len = strlen(state_info.enabled_po); - if(len > 0) + if (len > 0) { - state_info.enabled_po[len-1] = '\0'; + state_info.enabled_po[len - 1] = '\0'; } - memcpy(state_buf + MCLAGD_REPLY_INFO_HDR + mclag_num*sizeof(struct mclagd_state), - &state_info, sizeof(struct mclagd_state)); - mclag_num ++; + memcpy(state_buf + MCLAGD_REPLY_INFO_HDR + mclag_num * sizeof(struct mclagd_state), + &state_info, sizeof(struct mclagd_state)); + mclag_num++; - if ((mclag_num + 1)*sizeof(struct mclagd_state) > (state_buf_size - MCLAGD_REPLY_INFO_HDR)) + if ((mclag_num + 1) * sizeof(struct mclagd_state) > (state_buf_size - MCLAGD_REPLY_INFO_HDR)) { state_buf_size += MCLAGDCTL_CMD_SIZE; state_buf = (char*)realloc(state_buf, state_buf_size); @@ -130,7 +130,7 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) *buf = state_buf; *num = mclag_num; - if (mclag_id >0 && !id_exist) + if (mclag_id > 0 && !id_exist) return EXEC_TYPE_NO_EXIST_MCLAGID; return EXEC_TYPE_SUCCESS; @@ -160,7 +160,7 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id) LIST_FOREACH(csm, &(sys->csm_list), next) { - if (mclag_id >0) + if (mclag_id > 0) { if (csm->mlag_id == mclag_id) id_exist = 1; @@ -178,12 +178,12 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id) memcpy(mclagd_arp.ipv4_addr, show_ip_str(htonl(iccpd_arp->ipv4_addr)), 16); memcpy(mclagd_arp.mac_addr, iccpd_arp->mac_addr, 6); - memcpy(arp_buf + MCLAGD_REPLY_INFO_HDR +arp_num*sizeof(struct mclagd_arp_msg), - &mclagd_arp, sizeof(struct mclagd_arp_msg)); + memcpy(arp_buf + MCLAGD_REPLY_INFO_HDR + arp_num * sizeof(struct mclagd_arp_msg), + &mclagd_arp, sizeof(struct mclagd_arp_msg)); - arp_num ++; + arp_num++; - if ((arp_num + 1)*sizeof(struct mclagd_arp_msg) > (arp_buf_size - MCLAGD_REPLY_INFO_HDR)) + if ((arp_num + 1) * sizeof(struct mclagd_arp_msg) > (arp_buf_size - MCLAGD_REPLY_INFO_HDR)) { arp_buf_size += MCLAGDCTL_CMD_SIZE; arp_buf = (char*)realloc(arp_buf, arp_buf_size); @@ -196,7 +196,7 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id) *buf = arp_buf; *num = arp_num; - if (mclag_id >0 && !id_exist) + if (mclag_id > 0 && !id_exist) return EXEC_TYPE_NO_EXIST_MCLAGID; return EXEC_TYPE_SUCCESS; @@ -226,7 +226,7 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id) LIST_FOREACH(csm, &(sys->csm_list), next) { - if (mclag_id >0) + if (mclag_id > 0) { if (csm->mlag_id == mclag_id) id_exist = 1; @@ -247,12 +247,12 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id) memcpy(mclagd_mac.origin_ifname, iccpd_mac->origin_ifname, strlen(iccpd_mac->origin_ifname)); mclagd_mac.age_flag = iccpd_mac->age_flag; - memcpy(mac_buf + MCLAGD_REPLY_INFO_HDR + mac_num*sizeof(struct mclagd_mac_msg), - &mclagd_mac, sizeof(struct mclagd_mac_msg)); + memcpy(mac_buf + MCLAGD_REPLY_INFO_HDR + mac_num * sizeof(struct mclagd_mac_msg), + &mclagd_mac, sizeof(struct mclagd_mac_msg)); - mac_num ++; + mac_num++; - if ((mac_num + 1)*sizeof(struct mclagd_mac_msg) > (mac_buf_size -MCLAGD_REPLY_INFO_HDR)) + if ((mac_num + 1) * sizeof(struct mclagd_mac_msg) > (mac_buf_size - MCLAGD_REPLY_INFO_HDR)) { mac_buf_size += MCLAGDCTL_CMD_SIZE; mac_buf = (char*)realloc(mac_buf, mac_buf_size); @@ -265,13 +265,13 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id) *buf = mac_buf; *num = mac_num; - if (mclag_id >0 && !id_exist) + if (mclag_id > 0 && !id_exist) return EXEC_TYPE_NO_EXIST_MCLAGID; return EXEC_TYPE_SUCCESS; } -int iccp_local_if_dump(char * *buf, int *num,int mclag_id) +int iccp_local_if_dump(char * *buf, int *num, int mclag_id) { struct System *sys = NULL; struct CSM *csm = NULL; @@ -298,7 +298,7 @@ int iccp_local_if_dump(char * *buf, int *num,int mclag_id) LIST_FOREACH(csm, &(sys->csm_list), next) { - if (mclag_id >0) + if (mclag_id > 0) { if (csm->mlag_id == mclag_id) id_exist = 1; @@ -363,18 +363,18 @@ int iccp_local_if_dump(char * *buf, int *num,int mclag_id) { if (vlan_id != NULL ) { - if (str_size -len < 4) + if (str_size - len < 4) break; len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid); } } - memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num*sizeof(struct mclagd_local_if), - &mclagd_lif, sizeof(struct mclagd_local_if)); + memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num * sizeof(struct mclagd_local_if), + &mclagd_lif, sizeof(struct mclagd_local_if)); - lif_num ++; + lif_num++; - if ((lif_num + 1)*sizeof(struct mclagd_local_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR)) + if ((lif_num + 1) * sizeof(struct mclagd_local_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR)) { lif_buf_size += MCLAGDCTL_CMD_SIZE; lif_buf = (char*)realloc(lif_buf, lif_buf_size); @@ -387,7 +387,7 @@ int iccp_local_if_dump(char * *buf, int *num,int mclag_id) *buf = lif_buf; *num = lif_num; - if (mclag_id >0 && !id_exist) + if (mclag_id > 0 && !id_exist) return EXEC_TYPE_NO_EXIST_MCLAGID; return EXEC_TYPE_SUCCESS; @@ -416,7 +416,7 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) LIST_FOREACH(csm, &(sys->csm_list), next) { - if (mclag_id >0) + if (mclag_id > 0) { if (csm->mlag_id == mclag_id) id_exist = 1; @@ -452,12 +452,12 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) mclagd_pif.po_id = pif_po->po_id; mclagd_pif.po_active = pif_po->po_active; - memcpy(pif_buf + MCLAGD_REPLY_INFO_HDR + pif_num*sizeof(struct mclagd_peer_if), - &mclagd_pif, sizeof(struct mclagd_peer_if)); + memcpy(pif_buf + MCLAGD_REPLY_INFO_HDR + pif_num * sizeof(struct mclagd_peer_if), + &mclagd_pif, sizeof(struct mclagd_peer_if)); - pif_num ++; + pif_num++; - if ((pif_num + 1)*sizeof(struct mclagd_peer_if) > (pif_buf_size - MCLAGD_REPLY_INFO_HDR)) + if ((pif_num + 1) * sizeof(struct mclagd_peer_if) > (pif_buf_size - MCLAGD_REPLY_INFO_HDR)) { pif_buf_size += MCLAGDCTL_CMD_SIZE; pif_buf = (char*)realloc(pif_buf, pif_buf_size); @@ -470,7 +470,7 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) *buf = pif_buf; *num = pif_num; - if (mclag_id >0 && !id_exist) + if (mclag_id > 0 && !id_exist) return EXEC_TYPE_NO_EXIST_MCLAGID; return EXEC_TYPE_SUCCESS; diff --git a/src/iccpd/src/iccp_consistency_check.c b/src/iccpd/src/iccp_consistency_check.c index 39302a23be10..b48e4eb37a96 100644 --- a/src/iccpd/src/iccp_consistency_check.c +++ b/src/iccpd/src/iccp_consistency_check.c @@ -1,26 +1,26 @@ /* -* iccp_consistency_check.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -* -*/ + * iccp_consistency_check.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + * + */ #include "../include/iccp_consistency_check.h" #include "../include/system.h" @@ -51,18 +51,18 @@ static int iccp_check_interface_mode( char* ifname) struct PeerInterface* peer_if = NULL; local_if = local_if_find_by_name(ifname); - if(local_if == NULL) - return -2; + if (local_if == NULL) + return -2; csm = local_if->csm; - if(csm == NULL) - return -3; + if (csm == NULL) + return -3; peer_if = peer_if_find_by_name(csm, ifname); - if(peer_if == NULL) - return -4; + if (peer_if == NULL) + return -4; - if(peer_if->l3_mode != local_if->l3_mode) + if (peer_if->l3_mode != local_if->l3_mode) return -5; return 1; @@ -75,18 +75,18 @@ static int iccp_check_interface_layer3_addr(char* ifname) struct PeerInterface* peer_if = NULL; local_if = local_if_find_by_name(ifname); - if(local_if == NULL) - return -2; + if (local_if == NULL) + return -2; csm = local_if->csm; - if(csm == NULL) - return -3; + if (csm == NULL) + return -3; peer_if = peer_if_find_by_name(csm, ifname); - if(peer_if == NULL) - return -4; + if (peer_if == NULL) + return -4; - if(peer_if->ipv4_addr != local_if->ipv4_addr) + if (peer_if->ipv4_addr != local_if->ipv4_addr) return -5; return 1; @@ -101,26 +101,26 @@ static int iccp_check_interface_vlan(char* ifname) struct LocalInterface* local_if = NULL; local_if = local_if_find_by_name(ifname); - if(local_if == NULL) - return -2; + if (local_if == NULL) + return -2; csm = local_if->csm; - if(csm == NULL) - return -3; + if (csm == NULL) + return -3; peer_if = peer_if_find_by_name(csm, ifname); - if(peer_if == NULL) - return -4; + if (peer_if == NULL) + return -4; LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next) { LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) { - if(peer_vlan->vid == local_vlan->vid) + if (peer_vlan->vid == local_vlan->vid) break; } - if(peer_vlan == NULL) + if (peer_vlan == NULL) { return -5; } @@ -131,11 +131,11 @@ static int iccp_check_interface_vlan(char* ifname) LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next) { - if(peer_vlan->vid == local_vlan->vid) + if (peer_vlan->vid == local_vlan->vid) break; } - if(local_vlan == NULL) + if (local_vlan == NULL) { return -6; } @@ -151,22 +151,22 @@ static const ConsistencyCheckFunc check_func[] = { iccp_check_interface_vlan, /* REASON_PEER_IF_VLAN_IS_ASYNC */ NULL /* REASON_MAX_ARRAY_SIZE */ }; -#define ARRAY_SIZE(array_name) (sizeof(array_name)/sizeof(array_name[0])) +#define ARRAY_SIZE(array_name) (sizeof(array_name) / sizeof(array_name[0])) enum Reason_ID iccp_consistency_check(char* ifname) { int i = 0; int ret = 0; - for(i = REASON_INTERRFACE_MODE_IS_ASYNC; i < REASON_MAX_ARRAY_SIZE; ++i) + for (i = REASON_INTERRFACE_MODE_IS_ASYNC; i < REASON_MAX_ARRAY_SIZE; ++i) { - if(check_func[i] == NULL) + if (check_func[i] == NULL) continue; - ret = check_func[i](ifname) ; - if(ret != 1) + ret = check_func[i](ifname); + if (ret != 1) { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s ret = %d",reasons[i] ,ret); - fprintf(stdout,"%s \n",reasons[i]); + ICCPD_LOG_DEBUG(__FUNCTION__, "%s ret = %d", reasons[i], ret); + fprintf(stdout, "%s \n", reasons[i]); return i; } } diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c index b22822945a26..2c9f9af3a083 100644 --- a/src/iccpd/src/iccp_csm.c +++ b/src/iccpd/src/iccp_csm.c @@ -1,25 +1,25 @@ /* -* iccp_csm.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_csm.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -35,29 +35,29 @@ * * ***************************************/ #define ICCP_CSM_QUEUE_REINIT(list) \ - {\ - struct Msg* msg = NULL;\ - while (!TAILQ_EMPTY(&(list))) {\ - msg = TAILQ_FIRST(&(list));\ - TAILQ_REMOVE(&(list), msg, tail);\ - free(msg->buf);\ - free(msg);\ - }\ - TAILQ_INIT(&(list));\ + { \ + struct Msg* msg = NULL; \ + while (!TAILQ_EMPTY(&(list))) { \ + msg = TAILQ_FIRST(&(list)); \ + TAILQ_REMOVE(&(list), msg, tail); \ + free(msg->buf); \ + free(msg); \ + } \ + TAILQ_INIT(&(list)); \ } /***************************************** * Global * * ***************************************/ -char g_csm_buf[CSM_BUFFER_SIZE]={0}; +char g_csm_buf[CSM_BUFFER_SIZE] = { 0 }; uint32_t ICCP_MSG_ID = 0x1; /* Enter Connection State Machine NONEXISTENT handle function */ static void iccp_csm_enter_state_nonexistent(struct CSM* csm) { - iccp_csm_finalize(csm); + iccp_csm_finalize(csm); } /* Enter Connection State Machine INITIALIZED handle function */ @@ -89,7 +89,8 @@ static void iccp_csm_enter_state_connecting(struct CSM* csm) } /* Enter Connection State Machine OPERATIONAL handle function */ -static void iccp_csm_enter_state_operational(struct CSM* csm) { +static void iccp_csm_enter_state_operational(struct CSM* csm) +{ if (csm == NULL) return; @@ -102,7 +103,8 @@ void *iccp_get_csm() struct CSM* csm = NULL; struct System* sys = NULL; - if((sys = system_get_instance()) == NULL) { + if ((sys = system_get_instance()) == NULL) + { return NULL; } @@ -126,7 +128,7 @@ void iccp_csm_status_reset(struct CSM* csm, int all) { ICCP_CSM_QUEUE_REINIT(csm->msg_list); - if(all) + if (all) { bzero(csm, sizeof(struct CSM)); ICCP_CSM_QUEUE_REINIT(csm->msg_list); @@ -143,7 +145,7 @@ void iccp_csm_status_reset(struct CSM* csm, int all) csm->role_type = STP_ROLE_NONE; csm->sock_read_event_ptr = NULL; csm->peer_link_if = NULL; - csm->u_msg_in_count= 0x0; + csm->u_msg_in_count = 0x0; csm->i_msg_in_count = 0x0; csm->icc_msg_in_count = 0x0; csm->icc_msg_out_count = 0x0; @@ -168,11 +170,11 @@ void iccp_csm_finalize(struct CSM* csm) if (csm == NULL) return; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) return; /*If warm reboot, don't change port block and peer link MAC learning*/ - if(sys->warmboot_exit != WARM_REBOOT) + if (sys->warmboot_exit != WARM_REBOOT) { /* Clean all port block*/ peerlink_port_isolate_cleanup(csm); @@ -218,13 +220,13 @@ void iccp_csm_msg_list_finalize(struct CSM* csm) /* Send message to peer */ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len) { - LDPHdr* ldp_hdr = (LDPHdr*) buf; + LDPHdr* ldp_hdr = (LDPHdr*)buf; ICCParameter* param = NULL; if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0) return -1; - if(ntohs(ldp_hdr->msg_type) == MSG_T_CAPABILITY) + if (ntohs(ldp_hdr->msg_type) == MSG_T_CAPABILITY) param = (struct ICCParameter*)&buf[sizeof(LDPHdr)]; else param = (struct ICCParameter*)&buf[sizeof(ICCHdr)]; @@ -234,7 +236,7 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len) csm->msg_log.msg[csm->msg_log.end_index].type = ntohs(ldp_hdr->msg_type); csm->msg_log.msg[csm->msg_log.end_index].tlv = ntohs(param->type); ++csm->msg_log.end_index; - if(csm->msg_log.end_index >= 128) + if (csm->msg_log.end_index >= 128) csm->msg_log.end_index = 0; return write(csm->sock_fd, buf, msg_len); @@ -272,6 +274,7 @@ void iccp_csm_transit(struct CSM* csm) if (csm->sock_fd > 0 && scheduler_check_csm_config(csm) > 0) csm->current_state = ICCP_INITIALIZED; break; + case ICCP_INITIALIZED: if (msg) iccp_csm_correspond_from_msg(csm, msg); @@ -282,12 +285,14 @@ void iccp_csm_transit(struct CSM* csm) else if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x1) csm->current_state = ICCP_CAPREC; break; + case ICCP_CAPSENT: if (msg) iccp_csm_correspond_from_msg(csm, msg); if (csm->iccp_info.sender_capability_flag == 0x1 && csm->iccp_info.peer_capability_flag == 0x1) csm->current_state = ICCP_CAPREC; break; + case ICCP_CAPREC: if (msg) iccp_csm_correspond_from_msg(csm, msg); @@ -299,6 +304,7 @@ void iccp_csm_transit(struct CSM* csm) else if (csm->iccp_info.peer_rg_connect_flag == 0x1 && csm->iccp_info.status_code == 0x0) csm->current_state = ICCP_OPERATIONAL; break; + case ICCP_CONNECTING: if (msg) iccp_csm_correspond_from_msg(csm, msg); @@ -310,16 +316,19 @@ void iccp_csm_transit(struct CSM* csm) else if (csm->iccp_info.peer_rg_connect_flag == 0x1 && csm->iccp_info.status_code == 0x0) csm->current_state = ICCP_OPERATIONAL; break; + case ICCP_OPERATIONAL: if (msg) iccp_csm_correspond_from_msg(csm, msg); - if (csm->iccp_info.sender_rg_connect_flag == 0x0 || csm->iccp_info.peer_rg_connect_flag == 0x0) { + if (csm->iccp_info.sender_rg_connect_flag == 0x0 || csm->iccp_info.peer_rg_connect_flag == 0x0) + { memset(g_csm_buf, 0, CSM_BUFFER_SIZE); len = iccp_csm_prepare_iccp_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); iccp_csm_send(csm, g_csm_buf, len); csm->current_state = ICCP_CAPREC; } break; + default: break; } @@ -330,26 +339,32 @@ void iccp_csm_transit(struct CSM* csm) switch (csm->current_state) { - case ICCP_NONEXISTENT: - iccp_csm_enter_state_nonexistent(csm); - break; - case ICCP_INITIALIZED: - iccp_csm_enter_state_initialized(csm); - break; - case ICCP_CAPSENT: - /* Do nothing on this state */ - break; - case ICCP_CAPREC: - iccp_csm_enter_state_caprec(csm); - break; - case ICCP_CONNECTING: - iccp_csm_enter_state_connecting(csm); - break; - case ICCP_OPERATIONAL: - iccp_csm_enter_state_operational(csm); - break; - default: - break; + case ICCP_NONEXISTENT: + iccp_csm_enter_state_nonexistent(csm); + break; + + case ICCP_INITIALIZED: + iccp_csm_enter_state_initialized(csm); + break; + + case ICCP_CAPSENT: + /* Do nothing on this state */ + break; + + case ICCP_CAPREC: + iccp_csm_enter_state_caprec(csm); + break; + + case ICCP_CONNECTING: + iccp_csm_enter_state_connecting(csm); + break; + + case ICCP_OPERATIONAL: + iccp_csm_enter_state_operational(csm); + break; + + default: + break; } } /*if (csm->current_state != ICCP_NONEXISTENT && prev_state != csm->current_state) @@ -369,27 +384,35 @@ int iccp_csm_prepare_iccp_msg(struct CSM* csm, char* buf, size_t max_buf_size) case ICCP_NONEXISTENT: /* Do nothing on this state */ break; + case ICCP_INITIALIZED: msg_len = iccp_csm_prepare_capability_msg(csm, buf, max_buf_size); break; + case ICCP_CAPSENT: /* Do nothing on this state */ break; + case ICCP_CAPREC: - if (csm->iccp_info.status_code > 0x0) { + if (csm->iccp_info.status_code > 0x0) + { msg_len = iccp_csm_prepare_nak_msg(csm, buf, max_buf_size); break; } msg_len = iccp_csm_prepare_rg_connect_msg(csm, buf, max_buf_size); break; + case ICCP_CONNECTING: - if (csm->iccp_info.status_code > 0x0) { + if (csm->iccp_info.status_code > 0x0) + { msg_len = iccp_csm_prepare_nak_msg(csm, buf, max_buf_size); break; } break; + case ICCP_OPERATIONAL: - if (csm->iccp_info.peer_rg_connect_flag == 0x0) { + if (csm->iccp_info.peer_rg_connect_flag == 0x0) + { msg_len = iccp_csm_prepare_rg_disconnect_msg(csm, buf, max_buf_size); break; } @@ -402,8 +425,8 @@ int iccp_csm_prepare_iccp_msg(struct CSM* csm, char* buf, size_t max_buf_size) /* ICCP capability message handle function */ int iccp_csm_prepare_capability_msg(struct CSM* csm, char* buf, size_t max_buf_size) { - LDPHdr* ldp_hdr = (LDPHdr*) buf; - LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*) &buf[sizeof(LDPHdr)]; + LDPHdr* ldp_hdr = (LDPHdr*)buf; + LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*)&buf[sizeof(LDPHdr)]; size_t msg_len = sizeof(LDPHdr) + sizeof(LDPICCPCapabilityTLV); memset(buf, 0, max_buf_size); @@ -423,7 +446,7 @@ int iccp_csm_prepare_capability_msg(struct CSM* csm, char* buf, size_t max_buf_s cap->icc_parameter.len = htons(TLV_L_ICCP_CAPABILITY); cap->s_bit = csm->iccp_info.sender_capability_flag; - *(uint16_t *)((uint8_t *)cap+sizeof(ICCParameter)) = htons(*(uint16_t *)((uint8_t *)cap+sizeof(ICCParameter))); + *(uint16_t *)((uint8_t *)cap + sizeof(ICCParameter)) = htons(*(uint16_t *)((uint8_t *)cap + sizeof(ICCParameter))); cap->major_ver = 0x1; cap->minior_ver = 0x0; @@ -444,8 +467,8 @@ void iccp_csm_fill_icc_rg_id_tlv(struct CSM* csm, ICCHdr* icc_hdr) /* ICCP NAK message handle function */ int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) { - ICCHdr* icc_hdr = (ICCHdr*) buf; - NAKTLV* nak = (NAKTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + NAKTLV* nak = (NAKTLV*)&buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(NAKTLV); memset(buf, 0, max_buf_size); @@ -461,7 +484,7 @@ int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) nak->icc_parameter.u_bit = 0x0; nak->icc_parameter.f_bit = 0x0; nak->icc_parameter.type = htons(TLV_T_NAK); - nak->icc_parameter.len = htons(sizeof(((struct NAKTLV*) 0)->iccp_status_code) + sizeof(((struct NAKTLV*) 0)->rejected_msg_id)); + nak->icc_parameter.len = htons(sizeof(((struct NAKTLV*)0)->iccp_status_code) + sizeof(((struct NAKTLV*)0)->rejected_msg_id)); switch (csm->iccp_info.status_code) { @@ -469,6 +492,7 @@ int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) nak->iccp_status_code = htonl(csm->iccp_info.status_code); nak->rejected_msg_id = htonl(csm->iccp_info.rejected_msg_id); break; + /* Unsupported */ case STATUS_CODE_ICCP_CONNECTION_COUNT_EXCEEDED: case STATUS_CODE_ICCP_APP_CONNECTION_COUNT_EXCEEDED: @@ -487,8 +511,8 @@ int iccp_csm_prepare_nak_msg(struct CSM* csm, char* buf, size_t max_buf_size) /* ICCP RG connect handle function */ int iccp_csm_prepare_rg_connect_msg(struct CSM* csm, char* buf, size_t max_buf_size) { - ICCHdr* icc_hdr = (ICCHdr*) buf; - ICCSenderNameTLV* sender = (ICCSenderNameTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + ICCSenderNameTLV* sender = (ICCSenderNameTLV*)&buf[sizeof(ICCHdr)]; size_t name_len = strlen(csm->iccp_info.sender_name); size_t msg_len = sizeof(ICCHdr) + sizeof(ICCParameter) + name_len; @@ -514,8 +538,8 @@ int iccp_csm_prepare_rg_connect_msg(struct CSM* csm, char* buf, size_t max_buf_s /* ICCP RG disconnect handle function */ int iccp_csm_prepare_rg_disconnect_msg(struct CSM* csm, char* buf, size_t max_buf_size) { - ICCHdr* icc_hdr = (ICCHdr*) buf; - DisconnectCodeTLV* disconn_code = (DisconnectCodeTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + DisconnectCodeTLV* disconn_code = (DisconnectCodeTLV*)&buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(DisconnectCodeTLV); memset(buf, 0, max_buf_size); @@ -531,7 +555,7 @@ int iccp_csm_prepare_rg_disconnect_msg(struct CSM* csm, char* buf, size_t max_bu disconn_code->icc_parameter.u_bit = 0x0; disconn_code->icc_parameter.f_bit = 0x0; disconn_code->icc_parameter.type = htons(TLV_T_DISCONNECT_CODE); - disconn_code->icc_parameter.len = htons(sizeof(((struct DisconnectCodeTLV*) 0)->iccp_status_code)); + disconn_code->icc_parameter.len = htons(sizeof(((struct DisconnectCodeTLV*)0)->iccp_status_code)); disconn_code->iccp_status_code = htonl(csm->iccp_info.status_code); return msg_len; @@ -545,7 +569,7 @@ static void iccp_csm_check_id_from_msg(struct CSM* csm, struct Msg* msg) if (!csm || !msg || !msg->buf) return; - icc_hdr = (ICCHdr*) msg->buf; + icc_hdr = (ICCHdr*)msg->buf; /* Capability Message doesn't have ICC RG ID TLV */ if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) @@ -559,7 +583,8 @@ static void iccp_csm_check_id_from_msg(struct CSM* csm, struct Msg* msg) csm->iccp_info.status_code = 0x0; csm->iccp_info.rejected_msg_id = 0x0; } - } else if (ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id) != csm->iccp_info.icc_rg_id) + } + else if (ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id) != csm->iccp_info.icc_rg_id) { csm->iccp_info.status_code = STATUS_CODE_U_ICCP_RG; csm->iccp_info.rejected_msg_id = ntohl(icc_hdr->icc_rg_id_tlv.icc_rg_id); @@ -574,8 +599,8 @@ void iccp_csm_correspond_from_msg(struct CSM* csm, struct Msg* msg) if (csm == NULL || msg == NULL || msg->buf == NULL) return; - icc_hdr = (ICCHdr*) msg->buf; - NAKTLV* nak = (NAKTLV*)( icc_hdr+sizeof(ICCHdr)); + icc_hdr = (ICCHdr*)msg->buf; + NAKTLV* nak = (NAKTLV*)( icc_hdr + sizeof(ICCHdr)); iccp_csm_check_id_from_msg(csm, msg); if (icc_hdr->ldp_hdr.msg_type == MSG_T_CAPABILITY) @@ -605,18 +630,18 @@ void iccp_csm_correspond_from_msg(struct CSM* csm, struct Msg* msg) /* Receive capability message correspond function */ void iccp_csm_correspond_from_capability_msg(struct CSM* csm, struct Msg* msg) { - LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*) &(msg->buf)[sizeof(LDPHdr)]; + LDPICCPCapabilityTLV* cap = (LDPICCPCapabilityTLV*)&(msg->buf)[sizeof(LDPHdr)]; *(uint16_t *)cap = ntohs(*(uint16_t *)cap); - *(uint16_t *)((uint8_t *)cap+sizeof(ICCParameter)) = ntohs(*(uint16_t *)((uint8_t *)cap+sizeof(ICCParameter))); + *(uint16_t *)((uint8_t *)cap + sizeof(ICCParameter)) = ntohs(*(uint16_t *)((uint8_t *)cap + sizeof(ICCParameter))); if (cap->icc_parameter.u_bit == 0x1 - && cap->icc_parameter.f_bit == 0x0 - && cap->icc_parameter.type == TLV_T_ICCP_CAPABILITY - && ntohs(cap->icc_parameter.len) == (TLV_L_ICCP_CAPABILITY) - && cap->s_bit == 1 - && cap->major_ver == 0x1 - && cap->minior_ver == 0x0) + && cap->icc_parameter.f_bit == 0x0 + && cap->icc_parameter.type == TLV_T_ICCP_CAPABILITY + && ntohs(cap->icc_parameter.len) == (TLV_L_ICCP_CAPABILITY) + && cap->s_bit == 1 + && cap->major_ver == 0x1 + && cap->minior_ver == 0x0) { csm->iccp_info.peer_capability_flag = 0x1; } @@ -625,13 +650,13 @@ void iccp_csm_correspond_from_capability_msg(struct CSM* csm, struct Msg* msg) /* Receive RG connect message correspond function */ void iccp_csm_correspond_from_rg_connect_msg(struct CSM* csm, struct Msg* msg) { - ICCSenderNameTLV* sender = (ICCSenderNameTLV*) &(msg->buf)[sizeof(ICCHdr)]; + ICCSenderNameTLV* sender = (ICCSenderNameTLV*)&(msg->buf)[sizeof(ICCHdr)]; *(uint16_t *)sender = ntohs(*(uint16_t *)sender); if (sender->icc_parameter.u_bit == 0x0 && - sender->icc_parameter.f_bit == 0x0 && - sender->icc_parameter.type == TLV_T_ICC_SENDER_NAME) + sender->icc_parameter.f_bit == 0x0 && + sender->icc_parameter.type == TLV_T_ICC_SENDER_NAME) { csm->iccp_info.peer_rg_connect_flag = 0x1; } @@ -640,15 +665,15 @@ void iccp_csm_correspond_from_rg_connect_msg(struct CSM* csm, struct Msg* msg) /* Receive RG disconnect message correspond function */ void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM* csm, struct Msg* msg) { - DisconnectCodeTLV* diconn_code = (DisconnectCodeTLV*) &(msg->buf)[sizeof(ICCHdr)]; + DisconnectCodeTLV* diconn_code = (DisconnectCodeTLV*)&(msg->buf)[sizeof(ICCHdr)]; *(uint16_t *)diconn_code = ntohs(*(uint16_t *)diconn_code); if (diconn_code->icc_parameter.u_bit == 0x0 - && diconn_code->icc_parameter.f_bit == 0x0 - && diconn_code->icc_parameter.type == TLV_T_DISCONNECT_CODE - && ntohs(diconn_code->icc_parameter.len) == (TLV_L_DISCONNECT_CODE) - && ntohl(diconn_code->iccp_status_code) == (STATUS_CODE_ICCP_RG_REMOVED)) + && diconn_code->icc_parameter.f_bit == 0x0 + && diconn_code->icc_parameter.type == TLV_T_DISCONNECT_CODE + && ntohs(diconn_code->icc_parameter.len) == (TLV_L_DISCONNECT_CODE) + && ntohl(diconn_code->iccp_status_code) == (STATUS_CODE_ICCP_RG_REMOVED)) { csm->iccp_info.sender_rg_connect_flag = 0x0; csm->iccp_info.peer_rg_connect_flag = 0x0; @@ -663,7 +688,8 @@ void iccp_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) int type = -1; int i = 0; - if (csm == NULL) { + if (csm == NULL) + { if (msg != NULL) free(msg); return; @@ -672,7 +698,7 @@ void iccp_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) if (msg == NULL) return; - icc_hdr = (ICCHdr*) msg->buf; + icc_hdr = (ICCHdr*)msg->buf; *(uint16_t *)icc_hdr = ntohs(*(uint16_t *)icc_hdr); @@ -682,18 +708,18 @@ void iccp_csm_enqueue_msg(struct CSM* csm, struct Msg* msg) } else if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION) { - naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; + naktlv = (NAKTLV*)&msg->buf[sizeof(ICCHdr)]; - for(i=0; irejected_msg_id) == csm->msg_log.msg[i].msg_id) + if (ntohl(naktlv->rejected_msg_id) == csm->msg_log.msg[i].msg_id) { type = csm->msg_log.msg[i].type; break; } } - if(type == MSG_T_RG_APP_DATA) + if (type == MSG_T_RG_APP_DATA) app_csm_enqueue_msg(csm, msg); else TAILQ_INSERT_TAIL(&(csm->msg_list), msg, tail); @@ -727,14 +753,14 @@ int iccp_csm_init_msg(struct Msg** msg, char* data, int len) if (msg == NULL) return -2; - if(data == NULL || len <= 0) + if (data == NULL || len <= 0) return -1; - iccp_msg = (struct Msg*) malloc(sizeof(struct Msg)); + iccp_msg = (struct Msg*)malloc(sizeof(struct Msg)); if (iccp_msg == NULL) goto err_ret; - iccp_msg->buf = (char*) malloc(len); + iccp_msg->buf = (char*)malloc(len); if (iccp_msg->buf == NULL) goto err_ret; @@ -744,10 +770,11 @@ int iccp_csm_init_msg(struct Msg** msg, char* data, int len) return 0; -err_ret: - if(iccp_msg) + err_ret: + if (iccp_msg) { - if(iccp_msg->buf) free(iccp_msg->buf); + if (iccp_msg->buf) + free(iccp_msg->buf); free(iccp_msg); } @@ -757,9 +784,9 @@ int iccp_csm_init_msg(struct Msg** msg, char* data, int len) void iccp_csm_stp_role_count(struct CSM *csm) { /* decide the role, lower ip to be active & socket client*/ - if(csm->role_type == STP_ROLE_NONE) + if (csm->role_type == STP_ROLE_NONE) { - if(inet_addr(csm->sender_ip) < inet_addr(csm->peer_ip)) + if (inet_addr(csm->sender_ip) < inet_addr(csm->peer_ip)) { /* Active*/ ICCPD_LOG_INFO(__FUNCTION__, "Role: [Active]"); diff --git a/src/iccpd/src/iccp_ifm.c b/src/iccpd/src/iccp_ifm.c index 8dd3f61f9225..d97de7be938a 100644 --- a/src/iccpd/src/iccp_ifm.c +++ b/src/iccpd/src/iccp_ifm.c @@ -1,25 +1,25 @@ /* -* iccp_ifm.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_ifm.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -37,7 +37,7 @@ #include "../include/port.h" #include "../include/iccp_netlink.h" -#define fwd_neigh_state_valid(state) (state & (NUD_REACHABLE|NUD_STALE|NUD_DELAY|NUD_PROBE|NUD_PERMANENT)) +#define fwd_neigh_state_valid(state) (state & (NUD_REACHABLE | NUD_STALE | NUD_DELAY | NUD_PROBE | NUD_PERMANENT)) #ifndef NDA_RTA #define NDA_RTA(r) \ @@ -48,11 +48,12 @@ static int iccp_valid_handler(struct nl_msg *msg, void *arg) { struct nlmsghdr *nlh = nlmsg_hdr(msg); unsigned int event = 0; + if (nlh->nlmsg_type != RTM_NEWLINK) - return 0; + return 0; if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) - ICCPD_LOG_ERR(__FUNCTION__, "Unknown message type."); + ICCPD_LOG_ERR(__FUNCTION__, "Unknown message type."); return 0; } @@ -64,19 +65,19 @@ int iccp_sys_local_if_list_get_init() struct nl_cb *cb; struct nl_cb *orig_cb; struct rtgenmsg rt_hdr = { - .rtgen_family = AF_UNSPEC, + .rtgen_family = AF_UNSPEC, }; int ret; int retry = 1; if (!(sys = system_get_instance())) - return -1; + return -1; while (retry) { retry = 0; ret = nl_send_simple(sys->route_sock, RTM_GETLINK, NLM_F_DUMP, - &rt_hdr, sizeof(rt_hdr)); + &rt_hdr, sizeof(rt_hdr)); if (ret < 0) { ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); @@ -98,7 +99,7 @@ int iccp_sys_local_if_list_get_init() nl_cb_put(cb); if (ret < 0) { - ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error. ret = %d errno = %d ",ret, errno); + ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error. ret = %d errno = %d ", ret, errno); if (ret != -NLE_DUMP_INTR) return ret; retry = 1; @@ -108,7 +109,7 @@ int iccp_sys_local_if_list_get_init() return ret; } -static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) +static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) { struct System *sys = NULL; struct CSM *csm = NULL; @@ -135,10 +136,10 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) /* create ARP msg*/ memset(buf, 0, MAX_BUFSIZE); msg_len = sizeof(struct ARPMsg); - arp_msg = (struct ARPMsg*) &buf; + arp_msg = (struct ARPMsg*)&buf; arp_msg->op_type = ARP_SYNC_LIF; sprintf(arp_msg->ifname, "%s", arp_lif->name); - if(tb[NDA_DST]) + if (tb[NDA_DST]) memcpy(&arp_msg->ipv4_addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST])); if (tb[NDA_LLADDR]) memcpy(arp_msg->mac_addr, RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR])); @@ -146,10 +147,10 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) arp_msg->ipv4_addr = ntohl(arp_msg->ipv4_addr); ICCPD_LOG_DEBUG(__FUNCTION__, "arp msg type %d , state (%04X)(%d) ifindex [%d] (%s) ip %s , mac [%02X:%02X:%02X:%02X:%02X:%02X] ", - msgtype, ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), - ndm->ndm_ifindex, arp_lif->name, - show_ip_str(htonl(arp_msg->ipv4_addr)), - arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3],arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + msgtype, ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), + ndm->ndm_ifindex, arp_lif->name, + show_ip_str(htonl(arp_msg->ipv4_addr)), + arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); /*Debug*/ #if 1 @@ -160,8 +161,8 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) fprintf(stderr, " ifindex = [%d] (%s)\n", ndm->ndm_ifindex, arp_msg->ifname); fprintf(stderr, " IP = [%s]\n", show_ip_str(htonl(arp_msg->ipv4_addr))); fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n", - arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3], - arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], + arp_msg->mac_addr[4], arp_msg->mac_addr[5]); fprintf(stderr, "==============================\n"); #endif @@ -179,12 +180,13 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) { if ( !(vlan_id_list->vlan_itf - && vlan_id_list->vlan_itf->ifindex == ndm->ndm_ifindex)) + && vlan_id_list->vlan_itf->ifindex == ndm->ndm_ifindex)) continue; break; } - if (!vlan_id_list) continue; + if (!vlan_id_list) + continue; ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", lif_po->name, vlan_id_list->vlan_itf->name); @@ -192,7 +194,8 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) else { /* Is the ARP belong to a L3 mode MLAG itf?*/ - if (ndm->ndm_ifindex != lif_po->ifindex) continue; + if (ndm->ndm_ifindex != lif_po->ifindex) + continue; ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", lif_po->name); @@ -203,16 +206,19 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) break; } - if (lif_po) break; + if (lif_po) + break; } - if (!(csm && lif_po)) return; - if (!verify_arp) return; + if (!(csm && lif_po)) + return; + if (!verify_arp) + return; /* update lif ARP*/ TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { - arp_info = (struct ARPMsg*) msg->buf; + arp_info = (struct ARPMsg*)msg->buf; if (arp_info->ipv4_addr != arp_msg->ipv4_addr) continue; @@ -227,10 +233,10 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) else { /* update ARP*/ - if(arp_info->op_type != arp_msg->op_type - || strcmp(arp_info->ifname, arp_msg->ifname)!=0 + if (arp_info->op_type != arp_msg->op_type + || strcmp(arp_info->ifname, arp_msg->ifname) != 0 || memcmp(arp_info->mac_addr, arp_msg->mac_addr, - ETHER_ADDR_LEN) != 0) + ETHER_ADDR_LEN) != 0) { arp_update = 1; arp_info->op_type = arp_msg->op_type; @@ -253,7 +259,7 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) if (!msg) { arp_msg->op_type = ARP_SYNC_LIF; - if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len) == 0) { mlacp_enqueue_arp(csm, msg); ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", @@ -306,7 +312,7 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) fprintf(stderr, "\n======== ARP Info List ========\n"); TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { - arp_msg = (struct ARPMsg*) msg->buf; + arp_msg = (struct ARPMsg*)msg->buf; fprintf(stderr, "type %d,ifname %s , ip %s\n", arp_msg->op_type, arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr))); } fprintf(stderr, "==============================\n"); @@ -314,6 +320,7 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) /*TEST dump for dequeue ARP message*/ #if 0 + while (MLACP(csm).arp_updated && !TAILQ_EMPTY(&(MLACP(csm).arp_msg_list))) { msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list)); @@ -325,33 +332,34 @@ static void do_arp_request (struct ndmsg *ndm, struct rtattr *tb[], int msgtype) fprintf(stderr, " ifname = [%s]\n", arp_msg->ifname); fprintf(stderr, " IP = [%s]\n", show_ip_str(arp_msg->ipv4_addr)); fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n", - arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3], - arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], + arp_msg->mac_addr[4], arp_msg->mac_addr[5]); fprintf(stderr, "==============================\n"); free(msg->buf); free(msg); } + MLACP(csm).arp_updated = 0; #endif return; } -void ifm_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, int len) +void ifm_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len) { - while (RTA_OK (rta, len)) + while (RTA_OK(rta, len)) { if (rta->rta_type <= max) tb[rta->rta_type] = rta; - rta = RTA_NEXT (rta, len); + rta = RTA_NEXT(rta, len); } } -int do_one_neigh_request (struct nlmsghdr *n) +int do_one_neigh_request(struct nlmsghdr *n) { struct ndmsg *ndm = NLMSG_DATA(n); int len = n->nlmsg_len; - struct rtattr * tb[NDA_MAX+1]; + struct rtattr * tb[NDA_MAX + 1]; if (n->nlmsg_type == NLMSG_DONE) { @@ -407,7 +415,7 @@ int iccp_arp_get_init() struct nl_cb *cb; struct nl_cb *orig_cb; struct rtgenmsg rt_hdr = { - .rtgen_family = AF_UNSPEC, + .rtgen_family = AF_UNSPEC, }; int ret; int retry = 1; @@ -419,7 +427,7 @@ int iccp_arp_get_init() { retry = 0; ret = nl_send_simple(sys->route_sock, RTM_GETNEIGH, NLM_F_DUMP, - &rt_hdr, sizeof(rt_hdr)); + &rt_hdr, sizeof(rt_hdr)); if (ret < 0) { ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); @@ -453,7 +461,7 @@ int iccp_arp_get_init() } /*When received ARP packets from kernel, update arp information*/ -void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]) +void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]) { struct System *sys = NULL; struct CSM *csm = NULL; @@ -479,7 +487,7 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET /* create ARP msg*/ memset(buf, 0, MAX_BUFSIZE); msg_len = sizeof(struct ARPMsg); - arp_msg = (struct ARPMsg*) &buf; + arp_msg = (struct ARPMsg*)&buf; arp_msg->op_type = ARP_SYNC_LIF; sprintf(arp_msg->ifname, "%s", arp_lif->name); memcpy(&arp_msg->ipv4_addr, &addr, 4); @@ -493,8 +501,8 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET fprintf(stderr, " ifindex = [%d] (%s)\n", ifindex, arp_lif->name); fprintf(stderr, " IP = [%s]\n", show_ip_str(htonl(arp_msg->ipv4_addr))); fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n", - arp_msg->mac_addr[0],arp_msg->mac_addr[1],arp_msg->mac_addr[2],arp_msg->mac_addr[3], - arp_msg->mac_addr[4],arp_msg->mac_addr[5]); + arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], + arp_msg->mac_addr[4], arp_msg->mac_addr[5]); fprintf(stderr, "==============================\n"); #endif @@ -512,19 +520,21 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next) { if ( !(vlan_id_list->vlan_itf - && vlan_id_list->vlan_itf->ifindex == ifindex)) + && vlan_id_list->vlan_itf->ifindex == ifindex)) continue; break; } - if (!vlan_id_list) continue; + if (!vlan_id_list) + continue; ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", lif_po->name, vlan_id_list->vlan_itf->name); } else { /* Is the ARP belong to a L3 mode MLAG itf?*/ - if (ifindex != lif_po->ifindex) continue; + if (ifindex != lif_po->ifindex) + continue; ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", lif_po->name); } @@ -534,24 +544,27 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET break; } - if (lif_po) break; + if (lif_po) + break; } - if (!(csm && lif_po)) return; - if (!verify_arp) return; + if (!(csm && lif_po)) + return; + if (!verify_arp) + return; /* update lif ARP*/ TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { - arp_info = (struct ARPMsg*) msg->buf; + arp_info = (struct ARPMsg*)msg->buf; if (arp_info->ipv4_addr != arp_msg->ipv4_addr) continue; /* update ARP*/ - if(arp_info->op_type != arp_msg->op_type - || strcmp(arp_info->ifname, arp_msg->ifname)!=0 + if (arp_info->op_type != arp_msg->op_type + || strcmp(arp_info->ifname, arp_msg->ifname) != 0 || memcmp(arp_info->mac_addr, arp_msg->mac_addr, - ETHER_ADDR_LEN) != 0) + ETHER_ADDR_LEN) != 0) { arp_info->op_type = arp_msg->op_type; sprintf(arp_info->ifname, "%s", arp_msg->ifname); @@ -568,7 +581,7 @@ void do_arp_update (unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ET if (!msg) { arp_msg->op_type = ARP_SYNC_LIF; - if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len)==0) + if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len) == 0) { mlacp_enqueue_arp(csm, msg); ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", @@ -606,7 +619,7 @@ void iccp_from_netlink_port_state_handler( char * ifname, int state) struct System *sys; int po_is_active = 0; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); return; @@ -620,7 +633,7 @@ void iccp_from_netlink_port_state_handler( char * ifname, int state) /*If peer-link changes to down or up */ if (strcmp(ifname, csm->peer_itf_name) == 0) { - if(po_is_active == 0) + if (po_is_active == 0) mlacp_peerlink_down_handler(csm); else mlacp_peerlink_up_handler(csm); @@ -630,9 +643,9 @@ void iccp_from_netlink_port_state_handler( char * ifname, int state) LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) { - if(lif_po->type == IF_T_PORT_CHANNEL && strncmp(lif_po->name, ifname, MAX_L_PORT_NAME) == 0) + if (lif_po->type == IF_T_PORT_CHANNEL && strncmp(lif_po->name, ifname, MAX_L_PORT_NAME) == 0) { - mlacp_portchannel_state_handler(csm,lif_po,po_is_active); + mlacp_portchannel_state_handler(csm, lif_po, po_is_active); } } } @@ -641,57 +654,59 @@ void iccp_from_netlink_port_state_handler( char * ifname, int state) } int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, - int len, unsigned short flags) + int len, unsigned short flags) { - unsigned short type; + unsigned short type; - memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); - while (RTA_OK(rta, len)) - { - type = rta->rta_type & ~flags; - if ((type <= max) && (!tb[type])) - tb[type] = rta; - rta = RTA_NEXT(rta,len); - } + while (RTA_OK(rta, len)) + { + type = rta->rta_type & ~flags; + if ((type <= max) && (!tb[type])) + tb[type] = rta; + rta = RTA_NEXT(rta, len); + } - return 0; + return 0; } int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) { - return parse_rtattr_flags(tb, max, rta, len, 0); + return parse_rtattr_flags(tb, max, rta, len, 0); } - void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n) +void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n) { struct LocalInterface *lif = NULL; int msglen = 0; + msglen = n->nlmsg_len; + while (NLMSG_OK(n, msglen)) { struct ifinfomsg *ifm = NLMSG_DATA(n); int len = n->nlmsg_len; - struct rtattr * tb[IFLA_MAX+1]; + struct rtattr * tb[IFLA_MAX + 1]; if (n->nlmsg_type != RTM_NEWLINK) { - return ; + return; } len -= NLMSG_LENGTH(sizeof(*ifm)); if (len < 0) { ICCPD_LOG_WARN(__FUNCTION__, "BUG: wrong nlmsg len %d\n", len); - return ; + return; } if (ifm->ifi_family != AF_BRIDGE) { - return ; + return; } - if ((lif = local_if_find_by_ifindex(ifm->ifi_index)) !=NULL) + if ((lif = local_if_find_by_ifindex(ifm->ifi_index)) != NULL) { parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len); @@ -699,7 +714,7 @@ int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) if (!tb[IFLA_AF_SPEC]) { ICCPD_LOG_WARN(__FUNCTION__, "%d None\n", (ifm->ifi_index)); - return ; + return; } else { @@ -728,7 +743,7 @@ int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) /*After update vlan list, remove unused item*/ LIST_FOREACH(vlan, &(lif->vlan_list), port_next) { - if(vlan->vlan_removed == 1) + if (vlan->vlan_removed == 1) { ICCPD_LOG_DEBUG(__FUNCTION__, "Delete VLAN ID = %d from %s", vlan->vid, lif->name); diff --git a/src/iccpd/src/iccp_main.c b/src/iccpd/src/iccp_main.c index 4a258a7e5f57..0ca9c13211ed 100644 --- a/src/iccpd/src/iccp_main.c +++ b/src/iccpd/src/iccp_main.c @@ -1,25 +1,25 @@ /* -* iccp_main.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_main.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -42,7 +42,7 @@ int check_instance(char* pid_file_path) return -1; pid_file = open(pid_file_path, O_CREAT | O_RDWR, 0666); - if(pid_file <=0 ) + if (pid_file <= 0 ) { fprintf(stderr, "Can't open a pid file. Terminate.\n"); close(pid_file); @@ -108,10 +108,10 @@ static inline int iccpd_make_rundir(void) ret = mkdir(ICCPD_RUN_DIR, 0755); if (ret && errno != EEXIST) { - ICCPD_LOG_ERR(__FUNCTION__,"Failed to create directory \"%s\"", - ICCPD_RUN_DIR); + ICCPD_LOG_ERR(__FUNCTION__, "Failed to create directory \"%s\"", + ICCPD_RUN_DIR); - return -errno; + return -errno; } return 0; @@ -129,10 +129,10 @@ void iccpd_signal_handler(int sig) return; } -retry: + retry: err = write(sys->sig_pipe_w, &warmboot_flag, 1); if (err == -1 && errno == EINTR) - goto retry; + goto retry; return; } @@ -147,22 +147,25 @@ static int iccpd_signal_init(struct System* sys) err = pipe(fds); if (err) - return -errno; + return -errno; sys->sig_pipe_r = fds[0]; sys->sig_pipe_w = fds[1]; - if (sigemptyset(&ss) < 0) { + if (sigemptyset(&ss) < 0) + { ICCPD_LOG_ERR(__FUNCTION__, "sigemptyset(): %d", errno); goto close_pipe; } - if (sigaddset(&ss, SIGUSR1) < 0) { + if (sigaddset(&ss, SIGUSR1) < 0) + { ICCPD_LOG_ERR(__FUNCTION__, "sigaddset(): %d", errno); goto close_pipe; } - if (sigprocmask(SIG_UNBLOCK, &ss, NULL) < 0) { + if (sigprocmask(SIG_UNBLOCK, &ss, NULL) < 0) + { ICCPD_LOG_ERR(__FUNCTION__, "sigprocmask(): %d", errno); goto close_pipe; } @@ -172,7 +175,8 @@ static int iccpd_signal_init(struct System* sys) sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; - if (sigaction(SIGUSR1, &sa, NULL) < 0) { + if (sigaction(SIGUSR1, &sa, NULL) < 0) + { ICCPD_LOG_ERR(__FUNCTION__, "sigaction(): %d", errno); goto close_pipe; } @@ -180,17 +184,17 @@ static int iccpd_signal_init(struct System* sys) event.data.fd = fds[0]; event.events = EPOLLIN; err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, fds[0], &event); - if(err) + if (err) { goto close_pipe; } FD_SET( fds[0], &(sys->readfd)); - sys->readfd_count ++; + sys->readfd_count++; return 0; -close_pipe: + close_pipe: close(sys->sig_pipe_r); close(sys->sig_pipe_w); return err; @@ -205,13 +209,13 @@ int main(int argc, char* argv[]) err = iccpd_make_rundir(); if (err) - return 0; + return 0; if (getuid() != 0) { fprintf(stderr, "This program needs root permission to do device manipulation. " - "Please use sudo to execute it or change your user to root.\n"); + "Please use sudo to execute it or change your user to root.\n"); exit(EXIT_FAILURE); } @@ -262,7 +266,7 @@ int main(int argc, char* argv[]) scheduler_start(); system_finalize(); /*scheduler_finalize(); - log_finalize();*/ + log_finalize();*/ return EXIT_SUCCESS; } diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c index 4ec49faf7c9e..23e72c065f24 100644 --- a/src/iccpd/src/iccp_netlink.c +++ b/src/iccpd/src/iccp_netlink.c @@ -1,25 +1,25 @@ /* -* iccp_netlink.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * iccp_netlink.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -56,12 +56,12 @@ /** * SECTION: Netlink helpers */ - /* \cond HIDDEN_SYMBOLS */ +/* \cond HIDDEN_SYMBOLS */ #ifndef SOL_NETLINK #define SOL_NETLINK 270 #endif -#define ARRAY_SIZE(array_name) (sizeof(array_name)/sizeof(array_name[0])) +#define ARRAY_SIZE(array_name) (sizeof(array_name) / sizeof(array_name[0])) #ifndef NETLINK_BROADCAST_SEND_ERROR #define NETLINK_BROADCAST_SEND_ERROR 0x4 @@ -88,8 +88,8 @@ static int iccp_seq_check_handler(struct nl_msg *msg, void *arg) } int iccp_send_and_recv(struct System *sys, struct nl_msg *msg, - int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) { int ret; struct nl_cb *cb; @@ -124,6 +124,7 @@ int iccp_send_and_recv(struct System *sys, struct nl_msg *msg, */ acked = false; + while (!acked) { ret = nl_recvmsgs(sys->genric_sock, cb); @@ -135,7 +136,7 @@ int iccp_send_and_recv(struct System *sys, struct nl_msg *msg, } err = 0; -put_cb: + put_cb: nl_cb_put(cb); return err; } @@ -158,7 +159,7 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) sys = system_get_instance(); if (sys == NULL) - return 0; + return 0; genlmsg_parse(nlh, 0, attrs, TEAM_ATTR_MAX, NULL); @@ -175,7 +176,7 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) csm = local_if->csm; - if(csm) + if (csm) { if (!attrs[TEAM_ATTR_LIST_PORT]) return NL_SKIP; @@ -184,7 +185,7 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) { uint32_t member_index; - if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX, nl_port, NULL)) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to parse nested attributes."); return NL_SKIP; @@ -199,15 +200,15 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) member_index = nla_get_u32(port_attrs[TEAM_ATTR_PORT_IFINDEX]); local_if_member = local_if_find_by_ifindex(member_index); - if(local_if_member == NULL) + if (local_if_member == NULL) { ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance (%d).", - local_if->name, member_index); + local_if->name, member_index); continue; } - if(port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) + if (port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) { local_if_member->po_id = -1; mlacp_unbind_local_if(local_if_member); @@ -224,19 +225,19 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) { if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) { - if(strlen(temp_buf) != 0) - len += snprintf(temp_buf + len, 512-len,"%s", ","); + if (strlen(temp_buf) != 0) + len += snprintf(temp_buf + len, 512 - len, "%s", ","); - len += snprintf(temp_buf + len, 512-len,"%s",lif->name); + len += snprintf(temp_buf + len, 512 - len, "%s", lif->name); } } - if(strcmp(temp_buf,local_if->portchannel_member_buf)) + if (strcmp(temp_buf, local_if->portchannel_member_buf)) { memset(local_if->portchannel_member_buf, 0, 512); - memcpy(local_if->portchannel_member_buf,temp_buf,sizeof(local_if->portchannel_member_buf)-1); + memcpy(local_if->portchannel_member_buf, temp_buf, sizeof(local_if->portchannel_member_buf) - 1); - if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /* portchannel member changed, update port isolate attribute*/ update_peerlink_isolate_from_all_csm_lif(csm); @@ -246,7 +247,7 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) } else /*peerlink portchannel */ { - if(local_if->is_peer_link) + if (local_if->is_peer_link) { LIST_FOREACH(csm, &(sys->csm_list), next) { @@ -263,7 +264,7 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) { uint32_t member_index; - if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX,nl_port, NULL)) + if (nla_parse_nested(port_attrs, TEAM_ATTR_PORT_MAX, nl_port, NULL)) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to parse nested attributes."); return NL_SKIP; @@ -278,17 +279,17 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) member_index = nla_get_u32(port_attrs[TEAM_ATTR_PORT_IFINDEX]); local_if_member = local_if_find_by_ifindex(member_index); - if(local_if_member == NULL) + if (local_if_member == NULL) { ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance (%d).", - local_if->name, member_index); + local_if->name, member_index); continue; } - if(port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) + if (port_attrs[TEAM_ATTR_PORT_REMOVED] && local_if_member->po_id != -1) { - local_if_member->po_id = -1; - if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + local_if_member->po_id = -1; + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /*link removed from portchannel, must be enabled mac learn*/ set_peerlink_mlag_port_learn(local_if_member, 1); @@ -300,7 +301,7 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) { local_if_member->po_id = local_if->po_id; - if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /*link add to portchannel, must be disabled mac learn*/ set_peerlink_mlag_port_learn(local_if, 0); @@ -313,25 +314,25 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) { if (lif->type == IF_T_PORT && lif->po_id == local_if->po_id) { - if(strlen(temp_buf) != 0) - len += snprintf(temp_buf + len, 512-len,"%s", ","); + if (strlen(temp_buf) != 0) + len += snprintf(temp_buf + len, 512 - len, "%s", ","); - len += snprintf(temp_buf + len, 512-len,"%s",lif->name); + len += snprintf(temp_buf + len, 512 - len, "%s", lif->name); } } - if(strcmp(temp_buf,local_if->portchannel_member_buf)) - { - memset(local_if->portchannel_member_buf, 0, 512); - memcpy(local_if->portchannel_member_buf,temp_buf,sizeof(local_if->portchannel_member_buf)-1); - - if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) - { - /*peerlink portchannel member changed*/ - update_peerlink_isolate_from_all_csm_lif(csm); - csm->isolate_update_time = time(NULL); - } - } + if (strcmp(temp_buf, local_if->portchannel_member_buf)) + { + memset(local_if->portchannel_member_buf, 0, 512); + memcpy(local_if->portchannel_member_buf, temp_buf, sizeof(local_if->portchannel_member_buf) - 1); + + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + /*peerlink portchannel member changed*/ + update_peerlink_isolate_from_all_csm_lif(csm); + csm->isolate_update_time = time(NULL); + } + } } } @@ -349,29 +350,30 @@ int iccp_genric_socket_team_family_get() if (sys->family < 0) { sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + while (sys->family < 0) { sleep(1); - /*If no portchannel configuration, teamd will not started, genl_ctrl_resolve() will return <0 forever */ - /*Only log error message 5 times*/ + /*If no portchannel configuration, teamd will not started, genl_ctrl_resolve() will return <0 forever */ + /*Only log error message 5 times*/ ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink family. %d of TEAM_GENL_NAME %s ", sys->family, TEAM_GENL_NAME); - sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); } - grp_id = genl_ctrl_resolve_grp(sys->genric_sock, TEAM_GENL_NAME, - TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME); - if (grp_id < 0) - { - ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink multicast groups. %d", grp_id); - } + grp_id = genl_ctrl_resolve_grp(sys->genric_sock, TEAM_GENL_NAME, + TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME); + if (grp_id < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink multicast groups. %d", grp_id); + } - err = nl_socket_add_membership(sys->genric_event_sock, grp_id); - if (err < 0) - { - ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); + err = nl_socket_add_membership(sys->genric_event_sock, grp_id); + if (err < 0) + { + ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership."); } } @@ -386,7 +388,7 @@ int iccp_get_port_member_list(struct LocalInterface* lif) int err; sys = system_get_instance(); - if(sys == NULL) + if (sys == NULL) return 0; msg = nlmsg_alloc(); @@ -396,18 +398,18 @@ int iccp_get_port_member_list(struct LocalInterface* lif) err = iccp_genric_socket_team_family_get(); if (err) { - ICCPD_LOG_ERR(__FUNCTION__, "genric socket family get err err = %d . errno = %d", err , errno); + ICCPD_LOG_ERR(__FUNCTION__, "genric socket family get err err = %d . errno = %d", err, errno); return err; } genlmsg_put(msg, NL_AUTO_PID, sys->genric_sock_seq, sys->family, 0, 0, - TEAM_CMD_PORT_LIST_GET, 0); + TEAM_CMD_PORT_LIST_GET, 0); nla_put_u32(msg, TEAM_ATTR_TEAM_IFINDEX, lif->ifindex); err = iccp_send_and_recv(sys, msg, iccp_get_portchannel_member_list_handler, lif); if (err) { - ICCPD_LOG_ERR(__FUNCTION__, "recv msg err err = %d . errno = %d", err , errno); + ICCPD_LOG_ERR(__FUNCTION__, "recv msg err err = %d . errno = %d", err, errno); return err; } @@ -422,16 +424,17 @@ int iccp_netlink_if_hwaddr_set(uint32_t ifindex, uint8_t *addr, unsigned int add struct System* sys = NULL; if (!(sys = system_get_instance())) - return -1; + return -1; link = rtnl_link_alloc(); if (!link) - return -ENOMEM; + return -ENOMEM; - nl_addr = nl_addr_build(AF_UNSPEC, (void *) addr, addr_len); - if (!nl_addr) { - err = -ENOMEM; - goto errout; + nl_addr = nl_addr_build(AF_UNSPEC, (void *)addr, addr_len); + if (!nl_addr) + { + err = -ENOMEM; + goto errout; } rtnl_link_set_ifindex(link, ifindex); @@ -441,15 +444,15 @@ int iccp_netlink_if_hwaddr_set(uint32_t ifindex, uint8_t *addr, unsigned int add nl_addr_put(nl_addr); - errout: + errout: rtnl_link_put(link); return err; } #define SET_MAC_STR(buf, macArray) \ - snprintf(buf, 64, "%02x:%02x:%02x:%02x:%02x:%02x",\ - macArray[0],macArray[1],macArray[2], \ - macArray[3],macArray[4],macArray[5]); + snprintf(buf, 64, "%02x:%02x:%02x:%02x:%02x:%02x", \ + macArray[0], macArray[1], macArray[2], \ + macArray[3], macArray[4], macArray[5]); void iccp_set_interface_ipadd_mac(struct LocalInterface *lif, char * mac_addr ) { @@ -458,15 +461,16 @@ void iccp_set_interface_ipadd_mac(struct LocalInterface *lif, char * mac_addr ) char msg_buf[4096]; struct System *sys; - int src_len = 0,dst_len =0; + int src_len = 0, dst_len = 0; + sys = system_get_instance(); - if(sys == NULL) - return; + if (sys == NULL) + return; - memset(msg_buf,0,4095); + memset(msg_buf, 0, 4095); msg_hdr = (struct IccpSyncdHDr *)msg_buf; - msg_hdr->ver= 1; + msg_hdr->ver = 1; msg_hdr->type = MCLAG_MSG_TYPE_SET_MAC; msg_hdr->len = sizeof(struct IccpSyncdHDr); @@ -488,15 +492,15 @@ void iccp_set_interface_ipadd_mac(struct LocalInterface *lif, char * mac_addr ) dst_len = strlen(mac_addr); memcpy(sub_msg->data, mac_addr, dst_len); - ICCPD_LOG_DEBUG(__FUNCTION__,"lif name %s address %s mac msg data %s %d \n", lif->name , show_ip_str(htonl(lif->ipv4_addr)), sub_msg->data ,dst_len); + ICCPD_LOG_DEBUG(__FUNCTION__, "lif name %s address %s mac msg data %s %d \n", lif->name, show_ip_str(htonl(lif->ipv4_addr)), sub_msg->data, dst_len); sub_msg->op_len = dst_len; msg_hdr->len += sizeof(mclag_sub_option_hdr_t); msg_hdr->len += sub_msg->op_len; /*send msg*/ - if(sys->sync_fd) - write(sys->sync_fd,msg_buf, msg_hdr->len); + if (sys->sync_fd) + write(sys->sync_fd, msg_buf, msg_hdr->len); return; } @@ -506,6 +510,7 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) struct CSM* csm; uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; struct VLAN_ID *vlan = NULL; + csm = lif_po->csm; struct LocalInterface* lif_Bri; char macaddr[64]; @@ -514,7 +519,7 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) if (!csm) return; - if(lif_po->type != IF_T_PORT_CHANNEL) + if (lif_po->type != IF_T_PORT_CHANNEL) return; if (csm->role_type != STP_ROLE_STANDBY) @@ -522,53 +527,42 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) return; } - if(memcmp(MLACP(csm).remote_system.system_id, null_mac, ETHER_ADDR_LEN)==0) + if (memcmp(MLACP(csm).remote_system.system_id, null_mac, ETHER_ADDR_LEN) == 0) return; - /* set new mac*/ - if(memcmp( lif_po->mac_addr, MLACP(csm).remote_system.system_id,ETHER_ADDR_LEN)!= 0) + /*Set new mac*/ + if (memcmp( lif_po->mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN) != 0) { - /* backup old sysmac*/ - memcpy(lif_po->mac_addr_ori, lif_po->mac_addr, - ETHER_ADDR_LEN); + /*Backup old sysmac*/ + memcpy(lif_po->mac_addr_ori, lif_po->mac_addr, ETHER_ADDR_LEN); ICCPD_LOG_DEBUG(__FUNCTION__, - "%s Change the system-id of po%d from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", - (csm->role_type == STP_ROLE_STANDBY)?"Standby":"Active", - lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], - MLACP(csm).remote_system.system_id[0],MLACP(csm).remote_system.system_id[1],MLACP(csm).remote_system.system_id[2],MLACP(csm).remote_system.system_id[3],MLACP(csm).remote_system.system_id[4],MLACP(csm).remote_system.system_id[5]); + "%s Change the system-id of po%d from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", + (csm->role_type == STP_ROLE_STANDBY) ? "Standby" : "Active", + lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], + MLACP(csm).remote_system.system_id[0], MLACP(csm).remote_system.system_id[1], MLACP(csm).remote_system.system_id[2], MLACP(csm).remote_system.system_id[3], MLACP(csm).remote_system.system_id[4], MLACP(csm).remote_system.system_id[5]); - ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); + ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); if (ret != 0) { ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", lif_po->name, ret); } - /*set bridge mac back*/ - lif_Bri = local_if_find_by_name("Bridge"); - if (lif_Bri) - { - ret = iccp_netlink_if_hwaddr_set(lif_Bri->ifindex, lif_po->mac_addr_ori, ETHER_ADDR_LEN); - if (ret != 0) - { - ICCPD_LOG_ERR(__FUNCTION__, "ip link set dev Bridge mac error, ret = %d", ret); - } - } } - /*set portchannel ip mac */ - memset(macaddr,0,64); - SET_MAC_STR(macaddr,MLACP(csm).remote_system.system_id); - if(local_if_is_l3_mode(lif_po)) + /*Set portchannel ip mac */ + memset(macaddr, 0, 64); + SET_MAC_STR(macaddr, MLACP(csm).remote_system.system_id); + if (local_if_is_l3_mode(lif_po)) iccp_set_interface_ipadd_mac(lif_po, macaddr ); else { LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) { - if(!vlan->vlan_itf) + if (!vlan->vlan_itf) continue; - /* If the po is under a vlan, update vlan mac*/ - if(local_if_is_l3_mode(vlan->vlan_itf)) + /*If the po is under a vlan, update vlan mac*/ + if (local_if_is_l3_mode(vlan->vlan_itf)) { ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); if (ret != 0) @@ -589,6 +583,7 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) struct CSM* csm; uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; struct VLAN_ID *vlan = NULL; + csm = lif_po->csm; char macaddr[64]; int ret = 0; @@ -596,7 +591,7 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) if (!csm) return; - if(lif_po->type != IF_T_PORT_CHANNEL) + if (lif_po->type != IF_T_PORT_CHANNEL) return; if (csm->role_type != STP_ROLE_STANDBY) @@ -604,38 +599,38 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) return; } - /* recover mac to origin mac*/ - if(memcmp( lif_po->mac_addr, lif_po->mac_addr_ori, ETHER_ADDR_LEN)!= 0) + /*Recover mac to origin mac, it is the 'mac' value in 'localhost' currently*/ + if (memcmp( lif_po->mac_addr, MLACP(csm).system_id, ETHER_ADDR_LEN) != 0) { ICCPD_LOG_DEBUG(__FUNCTION__, - "%s Recove the system-id of po%d from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", - (csm->role_type == STP_ROLE_STANDBY)?"Standby":"Active", - lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], - lif_po->mac_addr_ori[0],lif_po->mac_addr_ori[1],lif_po->mac_addr_ori[2],lif_po->mac_addr_ori[3],lif_po->mac_addr_ori[4],lif_po->mac_addr_ori[5]); + "%s Recover the system-id of po%d from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", + (csm->role_type == STP_ROLE_STANDBY) ? "Standby" : "Active", + lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], + MLACP(csm).system_id[0], MLACP(csm).system_id[1], MLACP(csm).system_id[2], MLACP(csm).system_id[3], MLACP(csm).system_id[4], MLACP(csm).system_id[5]); - ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, lif_po->mac_addr_ori, ETHER_ADDR_LEN); + ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, MLACP(csm).system_id, ETHER_ADDR_LEN); if (ret != 0) { ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", lif_po->name, ret); } } - /*set portchannel ip mac */ - memset(macaddr,0,64); - SET_MAC_STR(macaddr, lif_po->mac_addr_ori); - if(local_if_is_l3_mode(lif_po)) + /*Set portchannel ip mac */ + memset(macaddr, 0, 64); + SET_MAC_STR(macaddr, MLACP(csm).system_id); + if (local_if_is_l3_mode(lif_po)) iccp_set_interface_ipadd_mac(lif_po, macaddr ); else { LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) { - if(!vlan->vlan_itf) + if (!vlan->vlan_itf) continue; - /* If the po is under a vlan, update vlan mac*/ - if(local_if_is_l3_mode(vlan->vlan_itf)) + /*If the po is under a vlan, update vlan mac*/ + if (local_if_is_l3_mode(vlan->vlan_itf)) { - ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, lif_po->mac_addr_ori, ETHER_ADDR_LEN); + ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, MLACP(csm).system_id, ETHER_ADDR_LEN); if (ret != 0) { ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", vlan->vlan_itf->name, ret); @@ -654,7 +649,7 @@ void update_local_system_id(struct LocalInterface* local_if) struct System* sys = NULL; struct CSM* csm = NULL; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); return; @@ -667,15 +662,15 @@ void update_local_system_id(struct LocalInterface* local_if) LIST_FOREACH(csm, &(sys->csm_list), next) { /* sync system info from one port-channel device*/ - if(memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) + if (memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) { memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); MLACP(csm).system_config_changed = 1; update_if_ipmac_on_standby(local_if); ICCPD_LOG_INFO(__FUNCTION__, - "update csm %d local system id to mac %02x:%02x:%02x:%02x:%02x:%02x of %s ", csm->mlag_id, local_if->mac_addr[0],local_if->mac_addr[1], - local_if->mac_addr[2],local_if->mac_addr[3],local_if->mac_addr[4],local_if->mac_addr[5], local_if->name ); + "update csm %d local system id to mac %02x:%02x:%02x:%02x:%02x:%02x of %s ", csm->mlag_id, local_if->mac_addr[0], local_if->mac_addr[1], + local_if->mac_addr[2], local_if->mac_addr[3], local_if->mac_addr[4], local_if->mac_addr[5], local_if->name ); } } @@ -694,7 +689,7 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) int op_state = 0; int link_flag = 0; - link = (struct rtnl_link *) obj; + link = (struct rtnl_link *)obj; ifindex = rtnl_link_get_ifindex(link); op_state = rtnl_link_get_operstate(link); ifname = rtnl_link_get_name(link); @@ -709,13 +704,13 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) if ((strncmp(ifname, VXLAN_TUNNEL_PREFIX, strlen(VXLAN_TUNNEL_PREFIX)) == 0)) { /*Change ifname from VTTNL0001-1000 to VTTNL0001*/ - if((p = strchr(ifname,'-')) != NULL) + if ((p = strchr(ifname, '-')) != NULL) { *p = '\0'; } /*Create vxlan tunnel dev, state is always UP*/ lif = local_if_find_by_name(ifname); - if(!lif) + if (!lif) { lif = local_if_create(ifindex, ifname, IF_T_VXLAN); lif->state = PORT_STATE_UP; @@ -728,25 +723,25 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) if (!lif) { const itf_type_t if_whitelist[] = { - {PORTCHANNEL_PREFIX,IF_T_PORT_CHANNEL}, - {VLAN_PREFIX, IF_T_VLAN}, - {FRONT_PANEL_PORT_PREFIX, IF_T_PORT}, - {VXLAN_TUNNEL_PREFIX, IF_T_VXLAN}, - {"Bri", IF_T_BRIDGE}, - {NULL, 0} }; + { PORTCHANNEL_PREFIX, IF_T_PORT_CHANNEL }, + { VLAN_PREFIX, IF_T_VLAN }, + { FRONT_PANEL_PORT_PREFIX, IF_T_PORT }, + { VXLAN_TUNNEL_PREFIX, IF_T_VXLAN }, + { NULL, 0 } + }; int i = 0; - for (i = 0; if_whitelist[i].ifname != NULL ; ++i) + for (i = 0; if_whitelist[i].ifname != NULL; ++i) { if ((strncmp(ifname, - if_whitelist[i].ifname, strlen(if_whitelist[i].ifname)) == 0)) + if_whitelist[i].ifname, strlen(if_whitelist[i].ifname)) == 0)) { lif = local_if_create(ifindex, ifname, if_whitelist[i].type); lif->state = PORT_STATE_DOWN; - if(IF_OPER_UP == op_state ) + if (IF_OPER_UP == op_state ) { lif->state = PORT_STATE_UP; } @@ -755,9 +750,8 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) { case AF_LLC: memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); - update_local_system_id(lif); default: - break; + break; } break; @@ -767,7 +761,7 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) else /*update*/ { /*update*/ - if(lif->state == PORT_STATE_DOWN && op_state == IF_OPER_UP) + if (lif->state == PORT_STATE_DOWN && op_state == IF_OPER_UP) { lif->state = PORT_STATE_UP; /*if(lif->type ==IF_T_PORT_CHANNEL)*/ @@ -775,7 +769,7 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); } - else if (lif->state == PORT_STATE_UP &&( IF_OPER_UP != op_state||!(link_flag&IFF_LOWER_UP))) + else if (lif->state == PORT_STATE_UP && ( IF_OPER_UP != op_state || !(link_flag & IFF_LOWER_UP))) { lif->state = PORT_STATE_DOWN; /*if(lif->type ==IF_T_PORT_CHANNEL)*/ @@ -786,16 +780,15 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) switch (addr_type) { - case AF_LLC: + case AF_LLC: if (memcmp(nl_addr_get_binary_addr(nl_addr), lif->mac_addr, ETHER_ADDR_LEN) != 0) { memcpy( lif->mac_addr, nl_addr_get_binary_addr(nl_addr), ETHER_ADDR_LEN); lif->port_config_sync = 1; - - update_local_system_id(lif); } - default: - break; + + default: + break; } } @@ -808,7 +801,7 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) struct LocalInterface *lif; uint32_t ifindex; - link = (struct rtnl_link *) obj; + link = (struct rtnl_link *)obj; ifindex = rtnl_link_get_ifindex(link); if ((lif = local_if_find_by_ifindex(ifindex)) != NULL) @@ -817,8 +810,8 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) return; } - int iccp_local_if_addr_update(struct nl_msg *msg, void *arg) - { +int iccp_local_if_addr_update(struct nl_msg *msg, void *arg) +{ int len; struct ifaddrmsg *ifa; struct LocalInterface *lif; @@ -828,7 +821,7 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR) return 0; - ifa = NLMSG_DATA (n); + ifa = NLMSG_DATA(n); if (ifa->ifa_family != AF_INET ) return 0; @@ -846,7 +839,7 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) lif->l3_mode = 0; } - len = n->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg)); + len = n->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)); if (len < 0) return 0; @@ -863,33 +856,33 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) lif->l3_mode = 1; lif->port_config_sync = 1; update_if_ipmac_on_standby(lif); - ICCPD_LOG_DEBUG(__FUNCTION__," if name %s index %d address %s \n",lif->name,lif->ifindex,show_ip_str(htonl(lif->ipv4_addr))); + ICCPD_LOG_DEBUG(__FUNCTION__, " if name %s index %d address %s \n", lif->name, lif->ifindex, show_ip_str(htonl(lif->ipv4_addr))); } rth = RTA_NEXT(rth, rtl); } return 0; - } +} - int iccp_sys_local_if_list_get_addr() +int iccp_sys_local_if_list_get_addr() { struct System *sys = NULL; struct nl_cb *cb; struct nl_cb *orig_cb; struct rtgenmsg rt_hdr = { - .rtgen_family = AF_UNSPEC, + .rtgen_family = AF_UNSPEC, }; int ret; int retry = 1; if (!(sys = system_get_instance())) - return -1; + return -1; while (retry) { retry = 0; ret = nl_send_simple(sys->route_sock, RTM_GETADDR, NLM_F_DUMP, - &rt_hdr, sizeof(rt_hdr)); + &rt_hdr, sizeof(rt_hdr)); if (ret < 0) { @@ -930,17 +923,20 @@ static int iccp_route_event_handler(struct nl_msg *msg, void *arg) { case RTM_NEWLINK: if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) - ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type. "); + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type. "); iccp_parse_if_vlan_info_from_netlink(nlh); break; + case RTM_DELLINK: if (nl_msg_parse(msg, &iccp_event_handler_obj_input_dellink, NULL) < 0) ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type."); break; + case RTM_NEWNEIGH: case RTM_DELNEIGH: do_one_neigh_request(nlh); break; + case RTM_NEWADDR: iccp_local_if_addr_update(msg, NULL); break; @@ -995,7 +991,7 @@ int iccp_system_init_netlink_socket() goto err_genric_event_sock_alloc; err = genl_connect(sys->genric_event_sock); - if(err) + if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->genric_event_sock."); goto err_genric_event_sock_connect; @@ -1003,10 +999,10 @@ int iccp_system_init_netlink_socket() sys->route_sock = nl_socket_alloc(); if (!sys->route_sock) - goto err_route_sock_alloc; + goto err_route_sock_alloc; err = nl_connect(sys->route_sock, NETLINK_ROUTE); if (err) - goto err_route_sock_connect; + goto err_route_sock_connect; err = nl_socket_set_buffer_size(sys->route_sock, 98304, 0); if (err) @@ -1020,7 +1016,7 @@ int iccp_system_init_netlink_socket() goto err_route_event_sock_alloc; err = nl_connect(sys->route_event_sock, NETLINK_ROUTE); - if(err) + if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to connect to netlink sys->route_event_sock. "); goto err_route_event_sock_connect; @@ -1035,7 +1031,7 @@ int iccp_system_init_netlink_socket() val = NETLINK_BROADCAST_SEND_ERROR; err = setsockopt(nl_socket_get_fd(sys->genric_event_sock), SOL_NETLINK, - NETLINK_BROADCAST_ERROR, &val, sizeof(val)); + NETLINK_BROADCAST_ERROR, &val, sizeof(val)); if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed set NETLINK_BROADCAST_ERROR on netlink event sock."); @@ -1057,13 +1053,14 @@ int iccp_system_init_netlink_socket() } #if 0 sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); + while (sys->family < 0) { sleep(1); log_err_period++; /*If no portchannel configuration, teamd will not started, genl_ctrl_resolve() will return <0 forever */ /*Only log error message 5 times*/ - if(log_err_period == 1 && log_err_time < 5) + if (log_err_period == 1 && log_err_time < 5) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink family. %d of TEAM_GENL_NAME %s ", sys->family, TEAM_GENL_NAME); log_err_time++; @@ -1071,7 +1068,7 @@ int iccp_system_init_netlink_socket() else { /*Log error message every 30s per time*/ - if(log_err_period == 30) + if (log_err_period == 30) log_err_period = 0; } @@ -1079,7 +1076,7 @@ int iccp_system_init_netlink_socket() } grp_id = genl_ctrl_resolve_grp(sys->genric_sock, TEAM_GENL_NAME, - TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME); + TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME); if (grp_id < 0) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink multicast groups. %d", grp_id); @@ -1095,11 +1092,11 @@ int iccp_system_init_netlink_socket() #endif nl_socket_disable_seq_check(sys->genric_event_sock); nl_socket_modify_cb(sys->genric_event_sock, NL_CB_VALID, NL_CB_CUSTOM, - iccp_genric_event_handler, sys); + iccp_genric_event_handler, sys); nl_socket_disable_seq_check(sys->route_event_sock); nl_socket_modify_cb(sys->route_event_sock, NL_CB_VALID, NL_CB_CUSTOM, - iccp_route_event_handler, sys); + iccp_route_event_handler, sys); err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_NEIGH); if (err < 0) @@ -1126,7 +1123,7 @@ int iccp_system_init_netlink_socket() sys->arp_receive_fd = socket(PF_PACKET, SOCK_DGRAM, 0); if (sys->arp_receive_fd < 0) { - ICCPD_LOG_ERR(__FUNCTION__,"socket error "); + ICCPD_LOG_ERR(__FUNCTION__, "socket error "); goto err_return; } @@ -1139,36 +1136,36 @@ int iccp_system_init_netlink_socket() sll.sll_ifindex = 0; if (bind(sys->arp_receive_fd, (struct sockaddr*)&sll, sizeof(sll)) < 0) { - ICCPD_LOG_ERR(__FUNCTION__,"socket bind error"); + ICCPD_LOG_ERR(__FUNCTION__, "socket bind error"); goto err_return; } } goto succes_return; -err_return: + err_return: -err_route_event_sock_connect: - nl_socket_free(sys->route_event_sock); + err_route_event_sock_connect: + nl_socket_free(sys->route_event_sock); -err_route_sock_alloc: -err_route_sock_connect: - nl_socket_free(sys->route_sock); + err_route_sock_alloc: + err_route_sock_connect: + nl_socket_free(sys->route_sock); -err_route_event_sock_alloc: -err_genric_event_sock_connect: + err_route_event_sock_alloc: + err_genric_event_sock_connect: nl_socket_free(sys->genric_event_sock); -err_genric_event_sock_alloc: -err_genric_sock_connect: + err_genric_event_sock_alloc: + err_genric_sock_connect: nl_socket_free(sys->genric_sock); return err; -err_genric_sock_alloc: + err_genric_sock_alloc: -succes_return: - return 0; + succes_return: + return 0; } void iccp_system_dinit_netlink_socket() @@ -1176,7 +1173,7 @@ void iccp_system_dinit_netlink_socket() struct System* sys = NULL; if ((sys = system_get_instance()) == NULL ) - return ; + return; nl_socket_free(sys->route_event_sock); nl_socket_free(sys->route_sock); @@ -1195,10 +1192,10 @@ static int iccp_netlink_genic_sock_event_handler(struct System *sys) int ret = 0; ret = nl_recvmsgs_default(sys->genric_event_sock); - if(ret) + if (ret) { sys->need_sync_team_again = 1; - ICCPD_LOG_DEBUG(__FUNCTION__, "genric_event_sock %d recvmsg error ret = %d ",nl_socket_get_fd(sys->genric_event_sock), ret); + ICCPD_LOG_DEBUG(__FUNCTION__, "genric_event_sock %d recvmsg error ret = %d ", nl_socket_get_fd(sys->genric_event_sock), ret); } return ret; @@ -1226,28 +1223,28 @@ static int iccp_receive_arp_packet_handler(struct System *sys) uint8_t mac_addr[ETHER_ADDR_LEN]; n = recvfrom(sys->arp_receive_fd, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr*)&sll, &sll_len); + (struct sockaddr*)&sll, &sll_len); if (n < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "arp recvfrom: %s",buf); + ICCPD_LOG_DEBUG(__FUNCTION__, "arp recvfrom: %s", buf); return -1; } /* Sanity checks */ /*Only process ARPOP_REPLY*/ if (n < sizeof(*a) || - a->ar_op != htons(ARPOP_REPLY) || + a->ar_op != htons(ARPOP_REPLY) || a->ar_pln != 4 || a->ar_pro != htons(ETH_P_IP) || a->ar_hln != sll.sll_halen || - sizeof(*a) + 2*4 + 2*a->ar_hln > n) - return 0; + sizeof(*a) + 2 * 4 + 2 * a->ar_hln > n) + return 0; ifindex = sll.sll_ifindex; - memcpy(mac_addr, (char*)(a+1), ETHER_ADDR_LEN); - memcpy(&addr, (char*)(a+1) + a->ar_hln, 4); + memcpy(mac_addr, (char*)(a + 1), ETHER_ADDR_LEN); + memcpy(&addr, (char*)(a + 1) + a->ar_hln, 4); - do_arp_update (ifindex, ntohl(addr), mac_addr); + do_arp_update(ifindex, ntohl(addr), mac_addr); return 0; } @@ -1258,9 +1255,9 @@ void iccp_netlink_sync_again() struct LocalInterface* lif = NULL; if ((sys = system_get_instance()) == NULL ) - return ; + return; - if(sys->need_sync_netlink_again) + if (sys->need_sync_netlink_again) { sys->need_sync_netlink_again = 0; @@ -1268,7 +1265,7 @@ void iccp_netlink_sync_again() iccp_sys_local_if_list_get_init(); } - if(sys->need_sync_team_again) + if (sys->need_sync_team_again) { sys->need_sync_team_again = 0; @@ -1290,13 +1287,13 @@ static int iccp_netlink_route_sock_event_handler(struct System *sys) ret = nl_recvmsgs_default(sys->route_event_sock); - if(ret) + if (ret) { sys->need_sync_netlink_again = 1; - ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d recvmsg error ret = %d errno = %d ",nl_socket_get_fd(sys->route_event_sock), ret, errno); + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d recvmsg error ret = %d errno = %d ", nl_socket_get_fd(sys->route_event_sock), ret, errno); } /*get netlink info again when error happens */ - if (ret ==0 && sys->need_sync_netlink_again == 1) + if (ret == 0 && sys->need_sync_netlink_again == 1) { iccp_netlink_sync_again(); } @@ -1308,7 +1305,8 @@ extern int iccp_get_receive_fdb_sock_fd(struct System *sys); extern int iccp_receive_fdb_handler_from_syncd(struct System *sys); /* cond HIDDEN_SYMBOLS */ -struct iccp_eventfd { +struct iccp_eventfd +{ int (*get_fd)(struct System* sys); int (*event_handler)(struct System* sys); }; @@ -1337,7 +1335,7 @@ static const struct iccp_eventfd iccp_eventfds[] = { #define ICCP_EVENT_FDS_COUNT ARRAY_SIZE(iccp_eventfds) /* \endcond */ /* -@return fd. + @return fd. * **/ @@ -1356,6 +1354,7 @@ int iccp_init_netlink_event_fd(struct System *sys) efd = epoll_create1(0); if (efd == -1) return -errno; + for (i = 0; i < ICCP_EVENT_FDS_COUNT; i++) { int fd = iccp_eventfds[i].get_fd(sys); @@ -1374,7 +1373,7 @@ int iccp_init_netlink_event_fd(struct System *sys) return 0; -close_efd: + close_efd: close(efd); return err; @@ -1389,7 +1388,7 @@ int iccp_init_netlink_event_fd(struct System *sys) int iccp_handle_events(struct System * sys) { - struct epoll_event events[ICCP_EVENT_FDS_COUNT+sys->readfd_count]; + struct epoll_event events[ICCP_EVENT_FDS_COUNT + sys->readfd_count]; struct CSM* csm = NULL; int nfds; int n; @@ -1397,7 +1396,7 @@ int iccp_handle_events(struct System * sys) int err; int max_nfds; - max_nfds = ICCP_EVENT_FDS_COUNT+sys->readfd_count; + max_nfds = ICCP_EVENT_FDS_COUNT + sys->readfd_count; nfds = epoll_wait(sys->epoll_fd, events, max_nfds, EPOLL_TIMEOUT_MSEC); @@ -1411,7 +1410,7 @@ int iccp_handle_events(struct System * sys) { err = eventfd->event_handler(sys); if (err) - ICCPD_LOG_INFO(__FUNCTION__, "Scheduler fd %d handler error %d !",events[i].data.fd, err ); + ICCPD_LOG_INFO(__FUNCTION__, "Scheduler fd %d handler error %d !", events[i].data.fd, err ); break; } } diff --git a/src/iccpd/src/logger.c b/src/iccpd/src/logger.c index dfa4bcbbcb1d..c2730093346e 100644 --- a/src/iccpd/src/logger.c +++ b/src/iccpd/src/logger.c @@ -1,25 +1,25 @@ /* -* logger.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * logger.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include #include @@ -44,14 +44,19 @@ static char* log_level_to_string(int level) { case CRITICAL_LOG_LEVEL: return "CRITICAL"; + case ERR_LOG_LEVEL: return "ERROR"; + case WARN_LOG_LEVEL: return "WARN"; - case NOTICE_LOG_LEVEL: + + case NOTICE_LOG_LEVEL: return "NOTICE"; + case INFO_LOG_LEVEL: return "INFO"; + case DEBUG_LOG_LEVEL: return "DEBUG"; } @@ -76,12 +81,13 @@ struct LoggerConfig* logger_get_configuration() void log_init(struct CmdOptionParser* parser) { struct LoggerConfig* config = logger_get_configuration(); + config->console_log_enabled = parser->console_log; } void log_finalize() { - /*do nothing*/ + /*do nothing*/ } void write_log(const int level, const char* tag, const char* format, ...) @@ -109,14 +115,14 @@ void write_log(const int level, const char* tag, const char* format, ...) va_end(args); /* Since osal_vsnprintf doesn't always return the exact size written to the buffer, - * we must check if the user string length exceeds the remaing buffer size. - */ + * we must check if the user string length exceeds the remaing buffer size. + */ if (print_len > avbl_buf_len) { print_len = avbl_buf_len; } - buf[prefix_len+print_len] = '\0'; + buf[prefix_len + print_len] = '\0'; ICCPD_UTILS_SYSLOG(_iccpd_log_level_map[level], "%s", buf); return; diff --git a/src/iccpd/src/mclagdctl/mclagdctl.c b/src/iccpd/src/mclagdctl/mclagdctl.c index 71af888e404b..6e6c1f1e2d75 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.c +++ b/src/iccpd/src/mclagdctl/mclagdctl.c @@ -1,24 +1,24 @@ /* - /* Copyright(c) 2016-2019 Nephos. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: Jim Jiang from nephos -*/ - + /* Copyright(c) 2016-2019 Nephos. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: Jim Jiang from nephos + */ + #include #include #include @@ -33,15 +33,15 @@ static int mclagdctl_sock_fd = -1; char *mclagdctl_sock_path = "/var/run/iccpd/mclagdctl.sock"; /* -Already implemented command: -mclagdctl -i dump state -mclagdctl -i dump arp -mclagdctl -i dump mac -mclagdctl -i dump portlist local -mclagdctl -i dump portlist peer -*/ - -static struct command_type command_types[] = + Already implemented command: + mclagdctl -i dump state + mclagdctl -i dump arp + mclagdctl -i dump mac + mclagdctl -i dump portlist local + mclagdctl -i dump portlist peer + */ + +static struct command_type command_types[] = { { .id = ID_CMDTYPE_D, @@ -50,50 +50,50 @@ static struct command_type command_types[] = .parse_msg = NULL, }, { - .id = ID_CMDTYPE_D_S, - .parent_id = ID_CMDTYPE_D, - .info_type = INFO_TYPE_DUMP_STATE, - .name = "state", - .enca_msg = mclagdctl_enca_dump_state, - .parse_msg = mclagdctl_parse_dump_state, + .id = ID_CMDTYPE_D_S, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_STATE, + .name = "state", + .enca_msg = mclagdctl_enca_dump_state, + .parse_msg = mclagdctl_parse_dump_state, }, { - .id = ID_CMDTYPE_D_A, - .parent_id = ID_CMDTYPE_D, - .info_type = INFO_TYPE_DUMP_ARP, - .name = "arp", - .enca_msg = mclagdctl_enca_dump_arp, - .parse_msg = mclagdctl_parse_dump_arp, + .id = ID_CMDTYPE_D_A, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_ARP, + .name = "arp", + .enca_msg = mclagdctl_enca_dump_arp, + .parse_msg = mclagdctl_parse_dump_arp, }, { - .id = ID_CMDTYPE_D_A, - .parent_id = ID_CMDTYPE_D, - .info_type = INFO_TYPE_DUMP_MAC, - .name = "mac", - .enca_msg = mclagdctl_enca_dump_mac, - .parse_msg = mclagdctl_parse_dump_mac, + .id = ID_CMDTYPE_D_A, + .parent_id = ID_CMDTYPE_D, + .info_type = INFO_TYPE_DUMP_MAC, + .name = "mac", + .enca_msg = mclagdctl_enca_dump_mac, + .parse_msg = mclagdctl_parse_dump_mac, }, { - .id = ID_CMDTYPE_D_P, - .parent_id = ID_CMDTYPE_D, - .name = "portlist", + .id = ID_CMDTYPE_D_P, + .parent_id = ID_CMDTYPE_D, + .name = "portlist", }, { - .id = ID_CMDTYPE_D_P_L, - .parent_id = ID_CMDTYPE_D_P, - .info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST, - .name = "local", - .enca_msg = mclagdctl_enca_dump_local_portlist, - .parse_msg = mclagdctl_parse_dump_local_portlist, + .id = ID_CMDTYPE_D_P_L, + .parent_id = ID_CMDTYPE_D_P, + .info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST, + .name = "local", + .enca_msg = mclagdctl_enca_dump_local_portlist, + .parse_msg = mclagdctl_parse_dump_local_portlist, }, { - .id = ID_CMDTYPE_D_P_P, - .parent_id = ID_CMDTYPE_D_P, - .info_type = INFO_TYPE_DUMP_PEER_PORTLIST, - .name = "peer", - .enca_msg = mclagdctl_enca_dump_peer_portlist, - .parse_msg = mclagdctl_parse_dump_peer_portlist, - }, + .id = ID_CMDTYPE_D_P_P, + .parent_id = ID_CMDTYPE_D_P, + .info_type = INFO_TYPE_DUMP_PEER_PORTLIST, + .name = "peer", + .enca_msg = mclagdctl_enca_dump_peer_portlist, + .parse_msg = mclagdctl_parse_dump_peer_portlist, + }, }; #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -105,15 +105,15 @@ int mclagdctl_sock_connect() int addrlen = 0; int ret = 0; - if(mclagdctl_sock_fd >= 0) + if (mclagdctl_sock_fd >= 0) return 0; - if(strlen(mclagdctl_sock_path) <= 0) + if (strlen(mclagdctl_sock_path) <= 0) return -1; mclagdctl_sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(mclagdctl_sock_fd < 0) + if (mclagdctl_sock_fd < 0) { return -1; } @@ -123,7 +123,7 @@ int mclagdctl_sock_connect() snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "%s", mclagdctl_sock_path); addrlen = sizeof(addr.sun_family) + strlen(mclagdctl_sock_path); - if((ret = connect(mclagdctl_sock_fd, (struct sockaddr*)&addr, addrlen)) < 0) + if ((ret = connect(mclagdctl_sock_fd, (struct sockaddr*)&addr, addrlen)) < 0) { close(mclagdctl_sock_fd); mclagdctl_sock_fd = -1; @@ -135,7 +135,7 @@ int mclagdctl_sock_connect() void mclagdctl_sock_close() { - if(mclagdctl_sock_fd > 0) + if (mclagdctl_sock_fd > 0) { close(mclagdctl_sock_fd); mclagdctl_sock_fd = -1; @@ -144,65 +144,67 @@ void mclagdctl_sock_close() return; } -int mclagdctl_sock_write(int fd, unsigned char *w_buf ,int total_len) +int mclagdctl_sock_write(int fd, unsigned char *w_buf, int total_len) { - int write_len =0; - int ret=0; - - while(write_len < total_len) + int write_len = 0; + int ret = 0; + + while (write_len < total_len) { ret = write(fd, w_buf + write_len, total_len - write_len); - if(ret <= 0) + if (ret <= 0) { return 0; } write_len += ret; } - + return write_len; } -int mclagdctl_sock_read(int fd, unsigned char *r_buf ,int total_len) +int mclagdctl_sock_read(int fd, unsigned char *r_buf, int total_len) { - int read_len=0; - int ret=0; - struct timeval tv = {0}; + int read_len = 0; + int ret = 0; + struct timeval tv = { 0 }; fd_set read_fd; - - while(read_len < total_len) + + while (read_len < total_len) { FD_ZERO(&read_fd); FD_SET(fd, &read_fd); tv.tv_sec = 10; tv.tv_usec = 0; - + switch ((ret = select(fd + 1, &read_fd, NULL, NULL, &tv))) { - case -1:// error - fprintf(stdout, "Mclagdctl:Select return error:%s\n", strerror(errno)); - return -1; - case 0:// timeout - fprintf(stdout, "Mclagdctl:Select timeout:%s\n", strerror(errno)); - return -1; - default: - break; + case -1: // error + fprintf(stdout, "Mclagdctl:Select return error:%s\n", strerror(errno)); + return -1; + + case 0: // timeout + fprintf(stdout, "Mclagdctl:Select timeout:%s\n", strerror(errno)); + return -1; + + default: + break; } - + ret = read(fd, r_buf + read_len, total_len - read_len); - if(ret <= 0) + if (ret <= 0) { return -1; } read_len += ret; } - + return read_len; } int mclagdctl_enca_dump_state(char *msg, int mclag_id, int argc, char **argv) { struct mclagdctl_req_hdr req; - + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); req.info_type = INFO_TYPE_DUMP_STATE; req.mclag_id = mclag_id; @@ -218,37 +220,38 @@ int mclagdctl_parse_dump_state(char *msg, int data_len) int count = 0; int pos = 0; - len = sizeof (struct mclagd_state); - for (; data_len >= len; data_len -=len, count ++) + len = sizeof(struct mclagd_state); + + for (; data_len >= len; data_len -= len, count++) { state_info = (struct mclagd_state*)(msg + len * count); - fprintf(stdout,"%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR"); - + fprintf(stdout, "%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR"); + if (state_info->mclag_id <= 0) - fprintf(stdout,"%s: %s\n", "Domain id", "Unknown"); + fprintf(stdout, "%s: %s\n", "Domain id", "Unknown"); else - fprintf(stdout,"%s: %d\n" ,"Domain id", state_info->mclag_id); - - fprintf(stdout,"%s: %s\n", "Local Ip", state_info->local_ip); - fprintf(stdout,"%s: %s\n", "Peer Ip", state_info->peer_ip); - fprintf(stdout,"%s: %s\n", "Peer Link Interface", state_info->peer_link_if); - - fprintf(stdout,"%s: %02x:%02x:%02x:%02x:%02x:%02x \n", - "Peer Link Mac", - state_info->peer_link_mac[0], state_info->peer_link_mac[1], - state_info->peer_link_mac[2], state_info->peer_link_mac[3], - state_info->peer_link_mac[4], state_info->peer_link_mac[5]); - + fprintf(stdout, "%s: %d\n", "Domain id", state_info->mclag_id); + + fprintf(stdout, "%s: %s\n", "Local Ip", state_info->local_ip); + fprintf(stdout, "%s: %s\n", "Peer Ip", state_info->peer_ip); + fprintf(stdout, "%s: %s\n", "Peer Link Interface", state_info->peer_link_if); + + fprintf(stdout, "%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + "Peer Link Mac", + state_info->peer_link_mac[0], state_info->peer_link_mac[1], + state_info->peer_link_mac[2], state_info->peer_link_mac[3], + state_info->peer_link_mac[4], state_info->peer_link_mac[5]); + if (state_info->role == 0) - fprintf(stdout,"%s: %s\n", "Role", "None"); + fprintf(stdout, "%s: %s\n", "Role", "None"); else if (state_info->role == 1) - fprintf(stdout,"%s: %s\n", "Role", "Active"); + fprintf(stdout, "%s: %s\n", "Role", "Active"); else if (state_info->role == 2) - fprintf(stdout,"%s: %s\n", "Role", "Standby"); - - fprintf(stdout,"%s: %s\n", "MCLAG Interface", state_info->enabled_po); - + fprintf(stdout, "%s: %s\n", "Role", "Standby"); + + fprintf(stdout, "%s: %s\n", "MCLAG Interface", state_info->enabled_po); + } return 0; @@ -283,22 +286,22 @@ int mclagdctl_parse_dump_arp(char *msg, int data_len) fprintf(stdout, "%-20s", "MAC"); fprintf(stdout, "%-20s", "DEV"); fprintf(stdout, "\n"); - - len = sizeof (struct mclagd_arp_msg); - - for (; data_len >= len; data_len -=len, count ++) - { - arp_info = (struct mclagd_arp_msg*)(msg + len * count); - - fprintf(stdout, "%-6d", count+1); + + len = sizeof(struct mclagd_arp_msg); + + for (; data_len >= len; data_len -= len, count++) + { + arp_info = (struct mclagd_arp_msg*)(msg + len * count); + + fprintf(stdout, "%-6d", count + 1); fprintf(stdout, "%-20s", arp_info->ipv4_addr); - fprintf(stdout,"%02x:%02x:%02x:%02x:%02x:%02x", - arp_info->mac_addr[0], arp_info->mac_addr[1], - arp_info->mac_addr[2], arp_info->mac_addr[3], - arp_info->mac_addr[4], arp_info->mac_addr[5]); + fprintf(stdout, "%02x:%02x:%02x:%02x:%02x:%02x", + arp_info->mac_addr[0], arp_info->mac_addr[1], + arp_info->mac_addr[2], arp_info->mac_addr[3], + arp_info->mac_addr[4], arp_info->mac_addr[5]); fprintf(stdout, " "); fprintf(stdout, "%-20s", arp_info->ifname); - fprintf(stdout, "\n"); + fprintf(stdout, "\n"); } return 0; @@ -327,7 +330,7 @@ int mclagdctl_parse_dump_mac(char *msg, int data_len) struct mclagd_mac_msg * mac_info = NULL; int len = 0; int count = 0; - + fprintf(stdout, "%-60s\n", "TYPE: S-STATIC, D-DYNAMIC; AGE: L-Local age, P-Peer age"); fprintf(stdout, "%-6s", "No."); @@ -338,30 +341,30 @@ int mclagdctl_parse_dump_mac(char *msg, int data_len) fprintf(stdout, "%-20s", "ORIGIN-DEV"); fprintf(stdout, "%-5s", "AGE"); fprintf(stdout, "\n"); - - len = sizeof (struct mclagd_mac_msg); - - for (; data_len >= len; data_len -=len, count ++) + + len = sizeof(struct mclagd_mac_msg); + + for (; data_len >= len; data_len -= len, count++) { mac_info = (struct mclagd_mac_msg*)(msg + len * count); fprintf(stdout, "%-6d", count + 1); - - if(mac_info->fdb_type == MAC_TYPE_STATIC_CTL) + + if (mac_info->fdb_type == MAC_TYPE_STATIC_CTL) fprintf(stdout, "%-5s", "S"); else fprintf(stdout, "%-5s", "D"); - + fprintf(stdout, "%-20s", mac_info->mac_str); fprintf(stdout, "%-5d", mac_info->vid); fprintf(stdout, "%-20s", mac_info->ifname); fprintf(stdout, "%-20s", mac_info->origin_ifname); - - if((mac_info->age_flag & MAC_AGE_LOCAL_CTL) && (mac_info->age_flag & MAC_AGE_PEER_CTL)) + + if ((mac_info->age_flag & MAC_AGE_LOCAL_CTL) && (mac_info->age_flag & MAC_AGE_PEER_CTL)) fprintf(stdout, "%-5s", "LP"); - else if(mac_info->age_flag & MAC_AGE_LOCAL_CTL) + else if (mac_info->age_flag & MAC_AGE_LOCAL_CTL) fprintf(stdout, "%-5s", "L"); - else if(mac_info->age_flag & MAC_AGE_PEER_CTL) + else if (mac_info->age_flag & MAC_AGE_PEER_CTL) fprintf(stdout, "%-5s", "P"); else fprintf(stdout, "%-5s", " "); @@ -380,7 +383,7 @@ int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc, char * fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); return -1; } - + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); req.info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; req.mclag_id = mclag_id; @@ -396,52 +399,53 @@ int mclagdctl_parse_dump_local_portlist(char *msg, int data_len) int count = 0; int pos = 0; - len = sizeof (struct mclagd_local_if); - - for (; data_len >= len; data_len -=len, count ++) + len = sizeof(struct mclagd_local_if); + + for (; data_len >= len; data_len -= len, count++) { - lif_info = (struct mclagd_local_if*)(msg + len * count); + lif_info = (struct mclagd_local_if*)(msg + len * count); for (pos = 0; pos < 60; ++pos) fprintf(stdout, "-"); + fprintf(stdout, "\n"); if (memcmp(lif_info->type, "PORT-CHANNEL", 12) == 0) - { - fprintf(stdout,"%s: %d\n" ,"Ifindex", lif_info->ifindex); - fprintf(stdout,"%s: %s\n", "Type", lif_info->type); - fprintf(stdout,"%s: %s\n", "PortName", lif_info->name); - fprintf(stdout,"%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + { + fprintf(stdout, "%s: %d\n", "Ifindex", lif_info->ifindex); + fprintf(stdout, "%s: %s\n", "Type", lif_info->type); + fprintf(stdout, "%s: %s\n", "PortName", lif_info->name); + fprintf(stdout, "%s: %02x:%02x:%02x:%02x:%02x:%02x \n", "MAC", lif_info->mac_addr[0], lif_info->mac_addr[1], lif_info->mac_addr[2], lif_info->mac_addr[3], lif_info->mac_addr[4], lif_info->mac_addr[5]); - - fprintf(stdout,"%s: %s\n", "IPv4Address", lif_info->ipv4_addr); - fprintf(stdout,"%s: %d\n" ,"Prefixlen", lif_info->prefixlen); - fprintf(stdout,"%s: %s\n", "State", lif_info->state); - fprintf(stdout,"%s: %s\n" ,"IsL3Interface", lif_info->l3_mode ? "Yes":"No"); - fprintf(stdout,"%s: %s\n" ,"IsPeerlink", lif_info->is_peer_link ? "Yes":"No"); - fprintf(stdout,"%s: %s\n", "MemberPorts", lif_info->portchannel_member_buf); + + fprintf(stdout, "%s: %s\n", "IPv4Address", lif_info->ipv4_addr); + fprintf(stdout, "%s: %d\n", "Prefixlen", lif_info->prefixlen); + fprintf(stdout, "%s: %s\n", "State", lif_info->state); + fprintf(stdout, "%s: %s\n", "IsL3Interface", lif_info->l3_mode ? "Yes" : "No"); + fprintf(stdout, "%s: %s\n", "IsPeerlink", lif_info->is_peer_link ? "Yes" : "No"); + fprintf(stdout, "%s: %s\n", "MemberPorts", lif_info->portchannel_member_buf); /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); - fprintf(stdout,"%s: %d\n" ,"PortchannelIsUp", lif_info->po_active); - fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state);*/ - fprintf(stdout,"%s: %s\n" ,"IsIsolateWithPeerlink", lif_info->isolate_to_peer_link ? "Yes":"No"); - fprintf(stdout,"%s: %s\n" ,"VlanList", lif_info->vlanlist); + fprintf(stdout,"%s: %d\n" ,"PortchannelIsUp", lif_info->po_active); + fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state);*/ + fprintf(stdout, "%s: %s\n", "IsIsolateWithPeerlink", lif_info->isolate_to_peer_link ? "Yes" : "No"); + fprintf(stdout, "%s: %s\n", "VlanList", lif_info->vlanlist); } else { - fprintf(stdout,"%s: %d\n" ,"Ifindex", lif_info->ifindex); - fprintf(stdout,"%s: %s\n", "Type", lif_info->type); - fprintf(stdout,"%s: %s\n", "PortName", lif_info->name); - fprintf(stdout,"%s: %s\n", "State", lif_info->state); + fprintf(stdout, "%s: %d\n", "Ifindex", lif_info->ifindex); + fprintf(stdout, "%s: %s\n", "Type", lif_info->type); + fprintf(stdout, "%s: %s\n", "PortName", lif_info->name); + fprintf(stdout, "%s: %s\n", "State", lif_info->state); /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id);*/ } - + for (pos = 0; pos < 60; ++pos) fprintf(stdout, "-"); - - fprintf(stdout, "\n\n"); + + fprintf(stdout, "\n\n"); } return 0; @@ -456,7 +460,7 @@ int mclagdctl_enca_dump_peer_portlist(char *msg, int mclag_id, int argc, char * fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); return -1; } - + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); req.info_type = INFO_TYPE_DUMP_PEER_PORTLIST; req.mclag_id = mclag_id; @@ -472,33 +476,34 @@ int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len) int count = 0; int pos = 0; - len = sizeof (struct mclagd_peer_if); - - for (; data_len >= len; data_len -=len, count ++) + len = sizeof(struct mclagd_peer_if); + + for (; data_len >= len; data_len -= len, count++) { - pif_info = (struct mclagd_peer_if*)(msg + len * count); + pif_info = (struct mclagd_peer_if*)(msg + len * count); for (pos = 0; pos < 60; ++pos) fprintf(stdout, "-"); + fprintf(stdout, "\n"); - - fprintf(stdout,"%s: %d\n" ,"Ifindex", pif_info->ifindex); - fprintf(stdout,"%s: %s\n", "Type", pif_info->type); - fprintf(stdout,"%s: %s\n", "PortName", pif_info->name); - fprintf(stdout,"%s: %02x:%02x:%02x:%02x:%02x:%02x \n", + + fprintf(stdout, "%s: %d\n", "Ifindex", pif_info->ifindex); + fprintf(stdout, "%s: %s\n", "Type", pif_info->type); + fprintf(stdout, "%s: %s\n", "PortName", pif_info->name); + fprintf(stdout, "%s: %02x:%02x:%02x:%02x:%02x:%02x \n", "MAC", pif_info->mac_addr[0], pif_info->mac_addr[1], pif_info->mac_addr[2], pif_info->mac_addr[3], pif_info->mac_addr[4], pif_info->mac_addr[5]); - - fprintf(stdout,"%s: %s\n", "State", pif_info->state); + + fprintf(stdout, "%s: %s\n", "State", pif_info->state); /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", pif_info->po_id); - fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", pif_info->po_active);*/ - + fprintf(stdout,"%s: %d\n" ,"PortchannelIsActive", pif_info->po_active);*/ + for (pos = 0; pos < 60; ++pos) fprintf(stdout, "-"); - - fprintf(stdout, "\n\n"); + + fprintf(stdout, "\n\n"); } return 0; @@ -508,31 +513,32 @@ static bool __mclagdctl_cmd_executable(struct command_type *cmd_type) { if (!cmd_type->enca_msg || !cmd_type->parse_msg) return 0; - + return 1; } static int __mclagdctl_cmd_param_cnt(struct command_type *cmd_type) { int i = 0; + while (cmd_type->params[i]) - i++; - + i++; + return i; } static struct command_type *__mclagdctl_get_cmd_by_parent(char *cmd_name, - enum id_command_type parent_id) + enum id_command_type parent_id) { int i; - for (i = 0; i < COMMAND_TYPE_COUNT; i++) + for (i = 0; i < COMMAND_TYPE_COUNT; i++) { - if (!strncmp(command_types[i].name, cmd_name, strlen(cmd_name)) + if (!strncmp(command_types[i].name, cmd_name, strlen(cmd_name)) && command_types[i].parent_id == parent_id) return &command_types[i]; } - + return NULL; } @@ -540,12 +546,12 @@ static struct command_type *__mclagdctl_get_cmd_by_id(enum id_command_type id) { int i; - for (i = 0; i < COMMAND_TYPE_COUNT; i++) + for (i = 0; i < COMMAND_TYPE_COUNT; i++) { if (command_types[i].id == id) - return &command_types[i]; + return &command_types[i]; } - + return NULL; } @@ -555,94 +561,99 @@ static int mclagdctl_find_cmd(struct command_type **pcmd_type, int *argc, char * enum id_command_type parent_id = ID_CMDTYPE_NONE; struct command_type *cmd_type; - while (1) + while (1) { - if (!*argc) + if (!*argc) { - fprintf(stderr, "None or incomplete command\n"); - return -EINVAL; - } - - cmd_name = *argv[0]; - (*argc)--; - (*argv)++; - cmd_type = __mclagdctl_get_cmd_by_parent(cmd_name, parent_id); - - if (!cmd_type) + fprintf(stderr, "None or incomplete command\n"); + return -EINVAL; + } + + cmd_name = *argv[0]; + (*argc)--; + (*argv)++; + cmd_type = __mclagdctl_get_cmd_by_parent(cmd_name, parent_id); + + if (!cmd_type) { - fprintf(stderr, "Unknown command \"%s\".\n", cmd_name); - return -EINVAL; - } - - if (__mclagdctl_cmd_executable(cmd_type) && __mclagdctl_cmd_param_cnt(cmd_type) >= *argc) - { - *pcmd_type = cmd_type; + fprintf(stderr, "Unknown command \"%s\".\n", cmd_name); + return -EINVAL; + } + + if (__mclagdctl_cmd_executable(cmd_type) && __mclagdctl_cmd_param_cnt(cmd_type) >= *argc) + { + *pcmd_type = cmd_type; return 0; - } - - parent_id = cmd_type->id; + } + + parent_id = cmd_type->id; } } static int mclagdctl_check_cmd_params(struct command_type *cmd_type, - int argc, char **argv) + int argc, char **argv) { int i = 0; - while (cmd_type->params[i]) + while (cmd_type->params[i]) { - if (i == argc) + if (i == argc) { fprintf(stderr, "Command line parameter \"%s\" expected.\n", cmd_type->params[i]); - return -EINVAL; - } - i++; + return -EINVAL; + } + i++; } + return 0; } static void mclagdctl_print_cmd(struct command_type *cmd_type) { - if (cmd_type->parent_id != ID_CMDTYPE_NONE) { - mclagdctl_print_cmd(__mclagdctl_get_cmd_by_id(cmd_type->parent_id)); - fprintf(stdout, " "); + if (cmd_type->parent_id != ID_CMDTYPE_NONE) + { + mclagdctl_print_cmd(__mclagdctl_get_cmd_by_id(cmd_type->parent_id)); + fprintf(stdout, " "); } fprintf(stdout, "%s", cmd_type->name); } -static void mclagdctl_print_help(const char *argv0) +static void mclagdctl_print_help(const char *argv0) { int i, j; struct command_type *cmd_type; fprintf(stdout, "%s [options] command [command args]\n" - " -h --help Show this help\n" - " -i --mclag-id Specify one mclag id\n", - argv0); + " -h --help Show this help\n" + " -i --mclag-id Specify one mclag id\n", + argv0); fprintf(stdout, "Commands:\n"); - for (i = 0; i < COMMAND_TYPE_COUNT; i++) + + for (i = 0; i < COMMAND_TYPE_COUNT; i++) { cmd_type = &command_types[i]; - if (!__mclagdctl_cmd_executable(cmd_type)) - continue; - fprintf(stdout, " "); - mclagdctl_print_cmd(cmd_type); - for (j = 0; cmd_type->params[j]; j++) - fprintf(stdout, " %s", cmd_type->params[j]); - fprintf(stdout, "\n"); - } + if (!__mclagdctl_cmd_executable(cmd_type)) + continue; + fprintf(stdout, " "); + mclagdctl_print_cmd(cmd_type); + + for (j = 0; cmd_type->params[j]; j++) + fprintf(stdout, " %s", cmd_type->params[j]); + + fprintf(stdout, "\n"); + } } int main(int argc, char **argv) { - char buf[MCLAGDCTL_CMD_SIZE]= {0}; - char *argv0 = argv[0]; + char buf[MCLAGDCTL_CMD_SIZE] = { 0 }; + char *argv0 = argv[0]; char *rcv_buf = NULL; - static const struct option long_options[] = + static const struct option long_options[] = { - { "help", no_argument, NULL, 'h' }, - { "mclag id", required_argument, NULL, 'i' }, - { NULL, 0, NULL, 0 } + { "help", no_argument, NULL, 'h' }, + { "mclag id", required_argument, NULL, 'i' }, + { NULL, 0, NULL, 0 } }; int opt; int err; @@ -653,24 +664,27 @@ int main(int argc, char **argv) char *data; struct mclagd_reply_hdr *reply; - while ((opt = getopt_long(argc, argv, "hi:", long_options, NULL)) >= 0) + while ((opt = getopt_long(argc, argv, "hi:", long_options, NULL)) >= 0) { - switch(opt) + switch (opt) { - case 'h': - mclagdctl_print_help(argv0); - return EXIT_SUCCESS; + case 'h': + mclagdctl_print_help(argv0); + return EXIT_SUCCESS; + case 'i': - mclag_id = atoi (optarg); - break; + mclag_id = atoi(optarg); + break; + case '?': - fprintf(stderr, "unknown option.\n"); - mclagdctl_print_help(argv0); - return EXIT_FAILURE; - default: - fprintf(stderr, "unknown option \"%c\".\n", opt); - mclagdctl_print_help(argv0); - return EXIT_FAILURE; + fprintf(stderr, "unknown option.\n"); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + + default: + fprintf(stderr, "unknown option \"%c\".\n", opt); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; } } @@ -678,23 +692,23 @@ int main(int argc, char **argv) argc -= optind; err = mclagdctl_find_cmd(&cmd_type, &argc, &argv); - if (err) + if (err) { - mclagdctl_print_help(argv0); - return EXIT_FAILURE; + mclagdctl_print_help(argv0); + return EXIT_FAILURE; } - + err = mclagdctl_check_cmd_params(cmd_type, argc, argv); if (err) { - mclagdctl_print_help(argv0); - return EXIT_FAILURE; + mclagdctl_print_help(argv0); + return EXIT_FAILURE; } - if (mclagdctl_sock_fd <= 0) + if (mclagdctl_sock_fd <= 0) { ret = mclagdctl_sock_connect(); - if(ret < 0) + if (ret < 0) return EXIT_FAILURE; } @@ -706,17 +720,17 @@ int main(int argc, char **argv) ret = mclagdctl_sock_write(mclagdctl_sock_fd, buf, sizeof(struct mclagdctl_req_hdr)); - if(ret <= 0) + if (ret <= 0) { fprintf(stderr, "Failed to send command to mclagd\n"); ret = EXIT_FAILURE; goto mclagdctl_disconnect; } - + /*read data length*/ memset(buf, 0, MCLAGDCTL_CMD_SIZE); ret = mclagdctl_sock_read(mclagdctl_sock_fd, buf, sizeof(int)); - if(ret <= 0) + if (ret <= 0) { fprintf(stderr, "Failed to read data length from mclagd\n"); ret = EXIT_FAILURE; @@ -725,7 +739,7 @@ int main(int argc, char **argv) /*cont length*/ len = *((int*)buf); - if(len <= 0) + if (len <= 0) { ret = EXIT_FAILURE; fprintf(stderr, "pkt len = %d, error\n", len); @@ -735,13 +749,13 @@ int main(int argc, char **argv) rcv_buf = (char *)malloc(len); if (!rcv_buf) { - fprintf(stderr, "Failed to malloc rcv_buf for mclagdctl\n"); - goto mclagdctl_disconnect; + fprintf(stderr, "Failed to malloc rcv_buf for mclagdctl\n"); + goto mclagdctl_disconnect; } - + /*read data*/ ret = mclagdctl_sock_read(mclagdctl_sock_fd, rcv_buf, len); - if(ret <= 0) + if (ret <= 0) { fprintf(stderr, "Failed to read data from mclagd\n"); ret = EXIT_FAILURE; @@ -749,7 +763,6 @@ int main(int argc, char **argv) } reply = (struct mclagd_reply_hdr *)rcv_buf; - if (reply->info_type != cmd_type->info_type) { fprintf(stderr, "Reply info type from mclagd error\n"); @@ -779,15 +792,15 @@ int main(int argc, char **argv) } cmd_type->parse_msg((char *)(rcv_buf + sizeof(struct mclagd_reply_hdr)), len - sizeof(struct mclagd_reply_hdr)); - + ret = EXIT_SUCCESS; - -mclagdctl_disconnect: + + mclagdctl_disconnect: mclagdctl_sock_close(); if (rcv_buf) free(rcv_buf); - + return ret; } diff --git a/src/iccpd/src/mclagdctl/mclagdctl.h b/src/iccpd/src/mclagdctl/mclagdctl.h index c71f536664ee..7da8d0817218 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.h +++ b/src/iccpd/src/mclagdctl/mclagdctl.h @@ -1,22 +1,22 @@ /* Copyright(c) 2016-2019 Nephos. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: Jim Jiang from nephos -*/ + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: Jim Jiang from nephos + */ #define MCLAGDCTL_PARA1_LEN 16 #define MCLAGDCTL_PARA2_LEN 32 @@ -31,17 +31,19 @@ typedef int (*call_enca_msg_fun)(char *msg, int mclag_id, int argc, char **argv); typedef int (*call_parse_msg_fun)(char *msg, int data_len); -enum MAC_TYPE_CTL { - MAC_TYPE_STATIC_CTL = 1, - MAC_TYPE_DYNAMIC_CTL = 2, +enum MAC_TYPE_CTL +{ + MAC_TYPE_STATIC_CTL = 1, + MAC_TYPE_DYNAMIC_CTL = 2, }; -enum MAC_AGE_TYPE_CTL { - MAC_AGE_LOCAL_CTL = 1,/*MAC in local switch is ageout*/ - MAC_AGE_PEER_CTL = 2/*MAC in peer switch is ageout*/ +enum MAC_AGE_TYPE_CTL +{ + MAC_AGE_LOCAL_CTL = 1, /*MAC in local switch is ageout*/ + MAC_AGE_PEER_CTL = 2 /*MAC in peer switch is ageout*/ }; -enum id_command_type +enum id_command_type { ID_CMDTYPE_NONE = 0, ID_CMDTYPE_D, @@ -52,9 +54,9 @@ enum id_command_type ID_CMDTYPE_D_P_P, }; -enum mclagdctl_notify_peer_type +enum mclagdctl_notify_peer_type { - INFO_TYPE_NONE = 0, + INFO_TYPE_NONE = 0, INFO_TYPE_DUMP_STATE, INFO_TYPE_DUMP_ARP, INFO_TYPE_DUMP_MAC, @@ -79,7 +81,7 @@ struct mclagd_reply_hdr int exec_result; }; -#define EXEC_TYPE_SUCCESS -1 +#define EXEC_TYPE_SUCCESS -1 #define EXEC_TYPE_NO_EXIST_SYS -2 #define EXEC_TYPE_NO_EXIST_MCLAGID -3 #define EXEC_TYPE_FAILED -4 @@ -87,11 +89,11 @@ struct mclagd_reply_hdr #define MCLAGD_REPLY_INFO_HDR (sizeof(struct mclagd_reply_hdr) + sizeof(int)) #define MCLAGDCTL_COMMAND_PARAM_MAX_CNT 8 -struct command_type +struct command_type { enum id_command_type id; enum id_command_type parent_id; - enum mclagdctl_notify_peer_type info_type; + enum mclagdctl_notify_peer_type info_type; char *name; char *params[MCLAGDCTL_COMMAND_PARAM_MAX_CNT]; call_enca_msg_fun enca_msg; @@ -110,29 +112,29 @@ struct mclagd_state char enabled_po[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; }; -struct mclagd_arp_msg +struct mclagd_arp_msg { - char op_type; + char op_type; char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN]; unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; }; -struct mclagd_mac_msg +struct mclagd_mac_msg { - unsigned char op_type;/*add or del*/ - unsigned char fdb_type;/*static or dynamic*/ + unsigned char op_type; /*add or del*/ + unsigned char fdb_type; /*static or dynamic*/ char mac_str[32]; unsigned short vid; /*Current if name that set in chip*/ char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; - /*if we set the mac to peer-link, origin_ifname store the - original if name that learned from chip*/ + /*if we set the mac to peer-link, origin_ifname store the + original if name that learned from chip*/ char origin_ifname[MCLAGDCTL_MAX_L_PORT_NANE]; unsigned char age_flag;/*local or peer is age?*/ }; -struct mclagd_local_if +struct mclagd_local_if { int ifindex; char type[MCLAGDCTL_PARA1_LEN]; @@ -141,14 +143,14 @@ struct mclagd_local_if char state[MCLAGDCTL_PARA1_LEN]; char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN]; unsigned char prefixlen; - + unsigned char l3_mode; unsigned char is_peer_link; char portchannel_member_buf[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; int po_id; /* Port Channel ID */ - unsigned char po_active; - char mlacp_state[MCLAGDCTL_PARA1_LEN]; - unsigned char isolate_to_peer_link; + unsigned char po_active; + char mlacp_state[MCLAGDCTL_PARA1_LEN]; + unsigned char isolate_to_peer_link; char vlanlist[MCLAGDCTL_PARA3_LEN]; }; diff --git a/src/iccpd/src/mlacp_fsm.c b/src/iccpd/src/mlacp_fsm.c index 3aff7801e670..4ca90a5ccda2 100644 --- a/src/iccpd/src/mlacp_fsm.c +++ b/src/iccpd/src/mlacp_fsm.c @@ -1,26 +1,26 @@ /* -* mlacp_fsm.c -* mLACP finite state machine handler. -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * mlacp_fsm.c + * mLACP finite state machine handler. + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -47,46 +47,46 @@ * * ***************************************/ #define MLACP_MSG_QUEUE_REINIT(list) \ - {\ - struct Msg* msg = NULL;\ - while (!TAILQ_EMPTY(&(list))) {\ - msg = TAILQ_FIRST(&(list));\ - TAILQ_REMOVE(&(list), msg, tail);\ - free(msg->buf);\ - free(msg);\ - }\ - TAILQ_INIT(&(list));\ + { \ + struct Msg* msg = NULL; \ + while (!TAILQ_EMPTY(&(list))) { \ + msg = TAILQ_FIRST(&(list)); \ + TAILQ_REMOVE(&(list), msg, tail); \ + free(msg->buf); \ + free(msg); \ + } \ + TAILQ_INIT(&(list)); \ } #define PIF_QUEUE_REINIT(list) \ { \ while (!LIST_EMPTY(&(list))) { \ - struct PeerInterface* peer_if = NULL;\ + struct PeerInterface* peer_if = NULL; \ peer_if = LIST_FIRST(&(list)); \ LIST_REMOVE(peer_if, mlacp_next); \ free(peer_if); \ } \ LIST_INIT(&(list)); \ } - + #define LIF_QUEUE_REINIT(list) \ { \ while (!LIST_EMPTY(&(list))) { \ - struct LocalInterface* lif = NULL;\ + struct LocalInterface* lif = NULL; \ lif = LIST_FIRST(&(list)); \ if (lif->type == IF_T_PORT_CHANNEL && lif->is_arp_accept) { \ if ((set_sys_arp_accept_flag(lif->name, 0)) == 0) \ - lif->is_arp_accept = 0; \ + lif->is_arp_accept = 0; \ } \ - LIST_REMOVE(lif, mlacp_next); \ + LIST_REMOVE (lif, mlacp_next); \ } \ LIST_INIT(&(list)); \ } - + #define LIF_PURGE_QUEUE_REINIT(list) \ { \ while (!LIST_EMPTY(&(list))) { \ - struct LocalInterface* lif = NULL;\ + struct LocalInterface* lif = NULL; \ lif = LIST_FIRST(&(list)); \ LIST_REMOVE(lif, mlacp_purge_next); \ } \ @@ -97,7 +97,7 @@ * Static Function * * ***************************************/ -static char *mlacp_state(struct CSM* csm) ; +static char *mlacp_state(struct CSM* csm); static void mlacp_resync_arp(struct CSM* csm); static void mlacp_resync_mac(struct CSM* csm); /* Sync Sender APIs*/ @@ -135,22 +135,22 @@ static void mlacp_stage_handler(struct CSM* csm, struct Msg* msg); static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg); /****************************************************************** -* Sync Sender APIs -* -*****************************************************************/ + * Sync Sender APIs + * + *****************************************************************/ static void mlacp_sync_send_sysConf(struct CSM* csm) { int msg_len = 0; - + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); msg_len = mlacp_prepare_for_sys_config(csm, g_csm_buf, CSM_BUFFER_SIZE); - if(msg_len > 0) + if (msg_len > 0) iccp_csm_send(csm, g_csm_buf, msg_len); else ICCPD_LOG_WARN("mlacp_fsm", " Invalid sysconf packet."); - + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] SysConf, len=[%d]", msg_len);*/ - + return; } @@ -159,13 +159,14 @@ static void mlacp_sync_send_aggConf(struct CSM* csm) struct System* sys = NULL; int msg_len = 0; struct LocalInterface* local_if = NULL; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return; - + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) { - if (local_if->type == IF_T_PORT_CHANNEL) { + if (local_if->type == IF_T_PORT_CHANNEL) + { memset(g_csm_buf, 0, CSM_BUFFER_SIZE); msg_len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if, 0); iccp_csm_send(csm, g_csm_buf, msg_len); @@ -173,8 +174,8 @@ static void mlacp_sync_send_aggConf(struct CSM* csm) /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ } } - - return; + + return; } static void mlacp_sync_send_aggState(struct CSM* csm) @@ -182,13 +183,14 @@ static void mlacp_sync_send_aggState(struct CSM* csm) struct System* sys = NULL; int msg_len = 0; struct LocalInterface* local_if = NULL; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return; - + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) { - if (local_if->type == IF_T_PORT_CHANNEL) { + if (local_if->type == IF_T_PORT_CHANNEL) + { memset(g_csm_buf, 0, CSM_BUFFER_SIZE); msg_len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if); iccp_csm_send(csm, g_csm_buf, msg_len); @@ -196,7 +198,7 @@ static void mlacp_sync_send_aggState(struct CSM* csm) /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ } } - + return; } @@ -204,7 +206,7 @@ static void mlacp_sync_send_syncMacInfo(struct CSM* csm) { int msg_len = 0; struct Msg* msg = NULL; - + while (!TAILQ_EMPTY(&(MLACP(csm).mac_msg_list))) { msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list)); @@ -216,7 +218,7 @@ static void mlacp_sync_send_syncMacInfo(struct CSM* csm) free(msg); /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] MacInfo,len=[%d]", msg_len);*/ } - + return; } @@ -224,7 +226,7 @@ static void mlacp_sync_send_syncArpInfo(struct CSM* csm) { int msg_len = 0; struct Msg* msg = NULL; - + while (!TAILQ_EMPTY(&(MLACP(csm).arp_msg_list))) { msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list)); @@ -236,7 +238,7 @@ static void mlacp_sync_send_syncArpInfo(struct CSM* csm) free(msg); /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] ArpInfo,len=[%d]", msg_len);*/ } - + return; } @@ -245,13 +247,14 @@ static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm) struct System* sys = NULL; int msg_len = 0; struct LocalInterface* local_if = NULL; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return; - + LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) { - if (local_if->type == IF_T_PORT_CHANNEL) { + if (local_if->type == IF_T_PORT_CHANNEL) + { memset(g_csm_buf, 0, CSM_BUFFER_SIZE); msg_len = mlacp_prepare_for_port_channel_info(csm, g_csm_buf, CSM_BUFFER_SIZE, local_if); iccp_csm_send(csm, g_csm_buf, msg_len); @@ -259,7 +262,7 @@ static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm) /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] PortChannel, csm-if-name=[%s], len=[%d]", local_if->name, msg_len);*/ } } - + return; } @@ -267,10 +270,10 @@ static void mlacp_sync_send_syncPeerLinkInfo(struct CSM* csm) { struct System* sys = NULL; int msg_len = 0; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return; - + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); msg_len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); iccp_csm_send(csm, g_csm_buf, msg_len); @@ -281,7 +284,7 @@ static void mlacp_sync_send_syncPeerLinkInfo(struct CSM* csm) static void mlacp_sync_send_heartbeat(struct CSM* csm) { int msg_len = 0; - + if ((csm->heartbeat_send_time == 0) || ((time(NULL) - csm->heartbeat_send_time) > 1)) { @@ -290,41 +293,41 @@ static void mlacp_sync_send_heartbeat(struct CSM* csm) iccp_csm_send(csm, g_csm_buf, msg_len); time(&csm->heartbeat_send_time); } - + return; } static void mlacp_sync_send_syncDoneData(struct CSM* csm) { int msg_len = 0; - + /*Sync done & go to next stage*/ - MLACP(csm).wait_for_sync_data = 0; - memset(g_csm_buf, 0 , CSM_BUFFER_SIZE); + MLACP(csm).wait_for_sync_data = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); msg_len = mlacp_prepare_for_sync_data_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE, 1); iccp_csm_send(csm, g_csm_buf, msg_len); /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] SyncDone, len=[%d]", msg_len);*/ - + return; } /****************************************************************** -* Sync Receiver APIs -* -*****************************************************************/ + * Sync Receiver APIs + * + *****************************************************************/ static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg) { - mLACPSysConfigTLV* sysconf = NULL; + mLACPSysConfigTLV* sysconf = NULL; sysconf = (mLACPSysConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); - - if(mlacp_fsm_update_system_conf(csm, sysconf)==-1) + + if (mlacp_fsm_update_system_conf(csm, sysconf) == -1) { /*NOTE: we just change the node ID local side without sending NAK msg*/ - ICCPD_LOG_DEBUG("mlacp_fsm", " Same Node ID = %d, send NAK",MLACP(csm).remote_system.node_id); + ICCPD_LOG_DEBUG("mlacp_fsm", " Same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id); mlacp_sync_send_nak_handler(csm, msg); } - + return; } @@ -349,97 +352,98 @@ static void mlacp_sync_recv_portState(struct CSM* csm, struct Msg* msg) static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg) { mLACPAggConfigTLV* portconf = NULL; - + portconf = (mLACPAggConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); if (mlacp_fsm_update_Agg_conf(csm, portconf) == -1) { mlacp_sync_send_nak_handler(csm, msg); } - - return; + + return; } static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg) { mLACPAggPortStateTLV* portstate = NULL; - - portstate = (mLACPAggPortStateTLV*) &(msg->buf[sizeof(ICCHdr)]); - if (mlacp_fsm_update_Aggport_state(csm, portstate) == -1) + + portstate = (mLACPAggPortStateTLV*)&(msg->buf[sizeof(ICCHdr)]); + if (mlacp_fsm_update_Aggport_state(csm, portstate) == -1) { mlacp_sync_send_nak_handler(csm, msg); /*MLACP(csm).error_msg = "Receive a port state update on an non-existed port. It is suggest to check the environment and re-initialize mLACP again.";*/ return; } - - return; + + return; } static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg) { mLACPSyncDataTLV* syncdata = NULL; - + syncdata = (mLACPSyncDataTLV*)&(msg->buf[sizeof(ICCHdr)]); - if(ntohs(syncdata->flags) == 1) + if (ntohs(syncdata->flags) == 1) { /* Sync done*/ MLACP(csm).wait_for_sync_data = 0; } - + return; } static void mlacp_sync_recv_syncReq(struct CSM* csm, struct Msg* msg) { mLACPSyncReqTLV* mlacp_sync_req = NULL; - mlacp_sync_req = (mLACPSyncReqTLV*) &msg->buf[sizeof(ICCHdr)]; + + mlacp_sync_req = (mLACPSyncReqTLV*)&msg->buf[sizeof(ICCHdr)]; MLACP(csm).sync_req_num = ntohs(mlacp_sync_req->req_num); - + /* Reply the peer all sync info*/ mlacp_sync_send_all_info_handler(csm); - + return; } static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg) { mLACPPortChannelInfoTLV* portconf = NULL; - + portconf = (mLACPPortChannelInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); if (mlacp_fsm_update_port_channel_info(csm, portconf) == -1) { mlacp_sync_send_nak_handler(csm, msg); } - + return; } static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg) { mLACPPeerLinkInfoTLV* peerlink = NULL; - + peerlink = (mLACPPeerLinkInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); mlacp_fsm_update_peerlink_info( csm, peerlink); - + return; } static void mlacp_sync_recv_macInfo(struct CSM* csm, struct Msg* msg) { struct mLACPMACInfoTLV* mac_info = NULL; - - mac_info = (struct mLACPMACInfoTLV *) &(msg->buf[sizeof(ICCHdr)]); + + mac_info = (struct mLACPMACInfoTLV *)&(msg->buf[sizeof(ICCHdr)]); mlacp_fsm_update_mac_info_from_peer(csm, mac_info); - + return; } static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg) { struct mLACPARPInfoTLV* arp_info = NULL; - - arp_info = (struct mLACPARPInfoTLV *) &(msg->buf[sizeof(ICCHdr)]); + + arp_info = (struct mLACPARPInfoTLV *)&(msg->buf[sizeof(ICCHdr)]); mlacp_fsm_update_arp_info(csm, arp_info); - + return; } @@ -452,20 +456,20 @@ static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg) static void mlacp_sync_recv_heartbeat(struct CSM* csm, struct Msg* msg) { struct mLACPHeartbeatTLV *tlv = NULL; - + tlv = (struct mLACPHeartbeatTLV *)(&msg->buf[sizeof(ICCHdr)]); mlacp_fsm_update_heartbeat(csm, tlv); - + return; } static void mlacp_sync_recv_warmboot(struct CSM* csm, struct Msg* msg) { struct mLACPWarmbootTLV *tlv = NULL; - + tlv = (struct mLACPWarmbootTLV *)(&msg->buf[sizeof(ICCHdr)]); mlacp_fsm_update_warmboot(csm, tlv); - + return; } @@ -475,34 +479,34 @@ static void mlacp_sync_recv_warmboot(struct CSM* csm, struct Msg* msg) * ***************************************/ void mlacp_init(struct CSM* csm, int all) { - if(csm == NULL) + if (csm == NULL) return; - + MLACP(csm).sync_req_num = -1; MLACP(csm).need_to_sync = 0; MLACP(csm).error_msg = NULL; - + MLACP(csm).current_state = MLACP_STATE_INIT; memset(MLACP(csm).remote_system.system_id, 0, ETHER_ADDR_LEN); - + MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); PIF_QUEUE_REINIT(MLACP(csm).pif_list); LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list); - + if (all != 0) { /* if no clean all, keep the arp info & local interface info for next connection*/ MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list); MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list); LIF_QUEUE_REINIT(MLACP(csm).lif_list); - + MLACP(csm).node_id = MLACP_SYSCONF_NODEID_MSB_MASK; MLACP(csm).node_id |= (((inet_addr(csm->sender_ip) >> 24) << 4) & MLACP_SYSCONF_NODEID_NODEID_MASK); MLACP(csm).node_id |= rand() % MLACP_SYSCONF_NODEID_FREE_MASK; } - + return; } @@ -514,20 +518,20 @@ void mlacp_finalize(struct CSM* csm) { if (csm == NULL) return; - + /* msg destroy*/ MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list); MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list); MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list); - + /* remove lif & lif-purge queue */ - LIF_QUEUE_REINIT(MLACP(csm).lif_list); + LIF_QUEUE_REINIT(MLACP(csm).lif_list); LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list); /* remove & destroy pif queue */ PIF_QUEUE_REINIT(MLACP(csm).pif_list); - + return; } @@ -535,25 +539,25 @@ void mlacp_finalize(struct CSM* csm) * MLACP FSM Transit * * ***************************************/ -void mlacp_fsm_transit(struct CSM* csm) +void mlacp_fsm_transit(struct CSM* csm) { struct System* sys = NULL; struct Msg* msg = NULL; static MLACP_APP_STATE_E prev_state = MLACP_SYNC_SYSCONF; ICCHdr* icc_hdr = NULL; ICCParameter* icc_param = NULL; - int have_msg=1; + int have_msg = 1; if (csm == NULL) return; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) return; /* torn down event */ if (csm->sock_fd <= 0 || csm->app_csm.current_state != APP_OPERATIONAL) { /* drop all legacy mlacp msg*/ - if (MLACP(csm).current_state != MLACP_STATE_INIT) + if (MLACP(csm).current_state != MLACP_STATE_INIT) { MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list); MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list); @@ -564,12 +568,12 @@ void mlacp_fsm_transit(struct CSM* csm) } /*Update port isolate after 3 seconds*/ - if(csm->isolate_update_time != 0 && (time(NULL) - csm->isolate_update_time) >= 3) + if (csm->isolate_update_time != 0 && (time(NULL) - csm->isolate_update_time) >= 3) { /*update_peerlink_isolate_from_all_csm_lif(csm);*/ csm->isolate_update_time = 0; } - + mlacp_sync_send_heartbeat(csm); /* Dequeue msg if any*/ @@ -579,11 +583,11 @@ void mlacp_fsm_transit(struct CSM* csm) { /* Handler NAK First*/ msg = mlacp_dequeue_msg(csm); - if (msg!=NULL) + if (msg != NULL) { - have_msg=1; - icc_hdr = (ICCHdr*) msg->buf; - icc_param = (ICCParameter*) &msg->buf[sizeof(ICCHdr)]; + have_msg = 1; + icc_hdr = (ICCHdr*)msg->buf; + icc_param = (ICCParameter*)&msg->buf[sizeof(ICCHdr)]; /*ICCPD_LOG_DEBUG("mlacp_fsm", " SYNC: Message Type = %X, TLV=%s, Len=%d", icc_hdr->ldp_hdr.msg_type, get_tlv_type_string(icc_param->type), msg->len);*/ if (icc_hdr->ldp_hdr.msg_type == MSG_T_NOTIFICATION && icc_param->type == TLV_T_NAK) @@ -592,42 +596,42 @@ void mlacp_fsm_transit(struct CSM* csm) free(msg->buf); free(msg); continue; - } + } } else { - have_msg=0; + have_msg = 0; } } - if (prev_state != MLACP(csm).current_state) + if (prev_state != MLACP(csm).current_state) { - if(MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) mlacp_peer_conn_handler(csm); prev_state = MLACP(csm).current_state; } - + /* Sync State */ - if (MLACP(csm).current_state == MLACP_STATE_INIT) + if (MLACP(csm).current_state == MLACP_STATE_INIT) { MLACP(csm).wait_for_sync_data = 0; MLACP(csm).current_state = MLACP_STATE_STAGE1; mlacp_resync_mac(csm); mlacp_resync_arp(csm); } - + switch (MLACP(csm).current_state) { case MLACP_STATE_INIT: case MLACP_STATE_ERROR: /* should not be here*/ break; - + case MLACP_STATE_STAGE1: case MLACP_STATE_STAGE2: mlacp_stage_handler(csm, msg); break; - + case MLACP_STATE_EXCHANGE: mlacp_exchange_handler(csm, msg); break; @@ -643,89 +647,93 @@ void mlacp_fsm_transit(struct CSM* csm) } /* Helper function for dumping application state machine */ -static char* mlacp_state(struct CSM* csm) +static char* mlacp_state(struct CSM* csm) { if (csm == NULL ) return "MLACP_NULL"; - + switch (MLACP(csm).current_state) { case MLACP_STATE_INIT: return "MLACP_STATE_INIT"; + case MLACP_STATE_STAGE1: return "MLACP_STATE_STAGE1"; + case MLACP_STATE_STAGE2: return "MLACP_STATE_STAGE2"; + case MLACP_STATE_EXCHANGE: return "MLACP_STATE_EXCHANGE"; + case MLACP_STATE_ERROR: return "MLACP_STATE_ERROR"; } - + return "MLACP_UNKNOWN"; } /* Add received message into message list */ -void mlacp_enqueue_msg(struct CSM* csm, struct Msg* msg) -{ - if (csm == NULL ) +void mlacp_enqueue_msg(struct CSM* csm, struct Msg* msg) +{ + if (csm == NULL ) { if (msg != NULL ) free(msg); return; } - + if (msg == NULL ) return; - + #if 0 - icc_hdr = (ICCHdr*) msg->buf; - icc_param = (ICCParameter*) &msg->buf[sizeof(ICCHdr)]; + icc_hdr = (ICCHdr*)msg->buf; + icc_param = (ICCParameter*)&msg->buf[sizeof(ICCHdr)]; ICCPD_LOG_DEBUG("mlacp_fsm", " mLACP enqueue: tlv = 0x%04x", icc_param->type); #endif - + TAILQ_INSERT_TAIL(&(MLACP(csm).mlacp_msg_list), msg, tail); return; } /* Get received message from message list */ -struct Msg* mlacp_dequeue_msg(struct CSM* csm) +struct Msg* mlacp_dequeue_msg(struct CSM* csm) { struct Msg* msg = NULL; - - if (!TAILQ_EMPTY(&(MLACP(csm).mlacp_msg_list))) + + if (!TAILQ_EMPTY(&(MLACP(csm).mlacp_msg_list))) { msg = TAILQ_FIRST(&(MLACP(csm).mlacp_msg_list)); TAILQ_REMOVE(&(MLACP(csm).mlacp_msg_list), msg, tail); } - + return msg; } /****************************************** * When peerlink ready, prepare the MACMsg -* +* ******************************************/ static void mlacp_resync_mac(struct CSM* csm) { struct Msg* msg = NULL; struct MACMsg* mac_msg = NULL; - struct Msg *msg_send = NULL; - + struct Msg *msg_send = NULL; + /* recover MAC info sync from peer*/ - if(!TAILQ_EMPTY(&(MLACP(csm).mac_list))) + if (!TAILQ_EMPTY(&(MLACP(csm).mac_list))) { TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { - mac_msg = (struct MACMsg*) msg->buf; + mac_msg = (struct MACMsg*)msg->buf; mac_msg->op_type = MAC_SYNC_ADD; if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { mac_msg->age_flag &= ~MAC_AGE_PEER; TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); } } } @@ -733,20 +741,20 @@ static void mlacp_resync_mac(struct CSM* csm) /****************************************** * When peerlink ready, prepare the ARPMsg -* +* ******************************************/ static void mlacp_resync_arp(struct CSM* csm) { struct Msg* msg = NULL; struct ARPMsg* arp_msg = NULL; - struct Msg *msg_send = NULL; - + struct Msg *msg_send = NULL; + /* recover ARP info sync from peer*/ - if(!TAILQ_EMPTY(&(MLACP(csm).arp_list))) + if (!TAILQ_EMPTY(&(MLACP(csm).arp_list))) { TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { - arp_msg = (struct ARPMsg*) msg->buf; + arp_msg = (struct ARPMsg*)msg->buf; arp_msg->op_type = ARP_SYNC_ADD; if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) { @@ -758,19 +766,19 @@ static void mlacp_resync_arp(struct CSM* csm) /***************************************** * NAK handler -* +* * ***************************************/ static void mlacp_sync_send_nak_handler(struct CSM* csm, struct Msg* msg) { int msg_len; ICCHdr* icc_hdr = NULL; - - icc_hdr = (ICCHdr*) msg->buf; - + + icc_hdr = (ICCHdr*)msg->buf; + ICCPD_LOG_WARN("mlacp_fsm", " ### Send NAK ###"); - + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); - csm->app_csm.invalid_msg_id = ntohl(icc_hdr->ldp_hdr.msg_id); + csm->app_csm.invalid_msg_id = ntohl(icc_hdr->ldp_hdr.msg_id); msg_len = app_csm_prepare_nak_msg(csm, g_csm_buf, CSM_BUFFER_SIZE); iccp_csm_send(csm, g_csm_buf, msg_len); } @@ -780,34 +788,34 @@ static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg) NAKTLV* naktlv = NULL; uint16_t tlvType = -1; int i; - + ICCPD_LOG_WARN("mlacp_fsm", " ### Receive NAK ###"); - + /* Dequeuq NAK*/ - naktlv = (NAKTLV*) &msg->buf[sizeof(ICCHdr)]; - + naktlv = (NAKTLV*)&msg->buf[sizeof(ICCHdr)]; + /* Check NAK Type*/ - for(i=0; irejected_msg_id) == csm->msg_log.msg[i].msg_id) + if (ntohl(naktlv->rejected_msg_id) == csm->msg_log.msg[i].msg_id) { tlvType = csm->msg_log.msg[i].tlv; break; } } - - if(tlvType) + + if (tlvType) { switch (tlvType) { case TLV_T_MLACP_SYSTEM_CONFIG: MLACP(csm).node_id--; - MLACP(csm).system_config_changed=1; - ICCPD_LOG_WARN("mlacp_fsm", " [%X] change NodeID as %d", tlvType&0x00FF, MLACP(csm).node_id); + MLACP(csm).system_config_changed = 1; + ICCPD_LOG_WARN("mlacp_fsm", " [%X] change NodeID as %d", tlvType & 0x00FF, MLACP(csm).node_id); break; - + default: - ICCPD_LOG_WARN("mlacp_fsm", " [%X]", tlvType&0x00FF); + ICCPD_LOG_WARN("mlacp_fsm", " [%X]", tlvType & 0x00FF); MLACP(csm).need_to_sync = 1; break; } @@ -823,81 +831,83 @@ static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg) /***************************************** * MLACP sync receiver -* +* * ***************************************/ static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg) { ICCParameter *icc_param; - + /* No receive message...*/ if (!csm || !msg) return; icc_param = (ICCParameter*)&(msg->buf[sizeof(ICCHdr)]); - + /*fprintf(stderr, " Recv Type [%d]\n", icc_param->type);*/ - switch(icc_param->type) + switch (icc_param->type) { case TLV_T_MLACP_SYSTEM_CONFIG: mlacp_sync_recv_sysConf(csm, msg); break; - + case TLV_T_MLACP_PORT_CONFIG: mlacp_sync_recv_portConf(csm, msg); break; - + case TLV_T_MLACP_PORT_PRIORITY: mlacp_sync_recv_portPrio(csm, msg); break; - + case TLV_T_MLACP_PORT_STATE: mlacp_sync_recv_portState(csm, msg); break; - + case TLV_T_MLACP_AGGREGATOR_CONFIG: /* The following line will be uncommented when Aggregator related structures are supported. */ mlacp_sync_recv_aggConf(csm, msg); break; - + case TLV_T_MLACP_AGGREGATOR_STATE: mlacp_sync_recv_aggState(csm, msg); break; - + case TLV_T_MLACP_SYNC_DATA: mlacp_sync_recv_syncData(csm, msg); break; - + case TLV_T_MLACP_SYNC_REQUEST: mlacp_sync_recv_syncReq(csm, msg); break; - + case TLV_T_MLACP_PORT_CHANNEL_INFO: mlacp_sync_recv_portChanInfo(csm, msg); break; - + case TLV_T_MLACP_PEERLINK_INFO: mlacp_sync_recv_peerLlinkInfo(csm, msg); break; - + case TLV_T_MLACP_MAC_INFO: mlacp_sync_recv_macInfo(csm, msg); break; - + case TLV_T_MLACP_ARP_INFO: mlacp_sync_recv_arpInfo(csm, msg); break; - + case TLV_T_MLACP_STP_INFO: mlacp_sync_recv_stpInfo(csm, msg); break; + case TLV_T_MLACP_HEARTBEAT: mlacp_sync_recv_heartbeat(csm, msg); break; + case TLV_T_MLACP_WARMBOOT_FLAG: mlacp_sync_recv_warmboot(csm, msg); break; } - + /*ICCPD_LOG_DEBUG("mlacp_fsm", " [Sync Recv] %s... DONE", get_tlv_type_string(icc_param->type));*/ return; @@ -905,26 +915,26 @@ static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg) /***************************************** * MLACP sync sender -* +* * ***************************************/ static void mlacp_sync_sender_handler(struct CSM* csm) { - switch(MLACP(csm).sync_state) + switch (MLACP(csm).sync_state) { case MLACP_SYNC_SYSCONF: mlacp_sync_send_sysConf(csm); break; - + case MLACP_SYNC_AGGCONF: /* Do nothing due to no support in this version. */ mlacp_sync_send_aggConf(csm); break; - + case MLACP_SYNC_AGGSTATE: /* Do nothing due to no support in this version. */ mlacp_sync_send_aggState(csm); break; - + case MLACP_SYNC_AGGINFO: mlacp_sync_send_syncPortChannelInfo(csm); break; @@ -936,14 +946,14 @@ static void mlacp_sync_sender_handler(struct CSM* csm) case MLACP_SYNC_ARP_INFO: mlacp_sync_send_syncArpInfo(csm); break; - + case MLACP_SYNC_DONE: mlacp_sync_send_syncDoneData(csm); break; - + default: break; - }; + } return; } @@ -951,21 +961,22 @@ static void mlacp_sync_sender_handler(struct CSM* csm) static void mlacp_sync_send_all_info_handler(struct CSM* csm) { size_t len = 0; - + /* Prepare for sync start reply*/ memset(g_csm_buf, 0, CSM_BUFFER_SIZE); len = mlacp_prepare_for_sync_data_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE, 0); iccp_csm_send(csm, g_csm_buf, len); - + MLACP(csm).sync_state = MLACP_SYNC_SYSCONF; - while(1) + + while (1) { mlacp_sync_sender_handler(csm); - if(MLACP(csm).sync_state != MLACP_SYNC_DONE) + if (MLACP(csm).sync_state != MLACP_SYNC_DONE) { MLACP(csm).sync_state++; } - else + else { /*Next stage*/ MLACP(csm).wait_for_sync_data = 0; @@ -982,20 +993,21 @@ static void mlacp_stage_sync_send_handler(struct CSM* csm, struct Msg* msg) ICCHdr* icc_hdr = NULL; ICCParameter* icc_param = NULL; mLACPSyncReqTLV* mlacp_sync_req = NULL; - + if (MLACP(csm).wait_for_sync_data == 0) { /* Waiting the peer sync request*/ - if(msg){ - icc_hdr = (ICCHdr*) msg->buf; - icc_param = (ICCParameter*) &msg->buf[sizeof(ICCHdr)]; - + if (msg) + { + icc_hdr = (ICCHdr*)msg->buf; + icc_param = (ICCParameter*)&msg->buf[sizeof(ICCHdr)]; + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA && icc_param->type == TLV_T_MLACP_SYNC_REQUEST) { - mlacp_sync_req = (mLACPSyncReqTLV*) &msg->buf[sizeof(ICCHdr)]; + mlacp_sync_req = (mLACPSyncReqTLV*)&msg->buf[sizeof(ICCHdr)]; MLACP(csm).wait_for_sync_data = 1; MLACP(csm).sync_req_num = ntohs(mlacp_sync_req->req_num); - + /* Reply the peer all sync info*/ mlacp_sync_send_all_info_handler(csm); } @@ -1007,7 +1019,8 @@ static void mlacp_stage_sync_send_handler(struct CSM* csm, struct Msg* msg) static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg) { - int msg_len=0; + int msg_len = 0; + /* Socket server send sync request first*/ if (MLACP(csm).wait_for_sync_data == 0) { @@ -1020,7 +1033,7 @@ static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg) else { mlacp_sync_receiver_handler(csm, msg); - if(MLACP(csm).wait_for_sync_data == 0) + if (MLACP(csm).wait_for_sync_data == 0) { MLACP(csm).current_state++; } @@ -1031,7 +1044,7 @@ static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg) static void mlacp_stage_handler(struct CSM* csm, struct Msg* msg) { - if(MLACP(csm).current_state==MLACP_STATE_STAGE1) + if (MLACP(csm).current_state == MLACP_STATE_STAGE1) { /*Stage 1, role active send info first*/ if (csm->role_type == STP_ROLE_ACTIVE) @@ -1059,17 +1072,17 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) ICCHdr* icc_hdr = NULL; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) return; - + /* update system id*/ /*update_system_id(csm);*/ /* Any msg?*/ - if (msg) + if (msg) { - icc_hdr = (ICCHdr*) msg->buf; - if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) + icc_hdr = (ICCHdr*)msg->buf; + if (icc_hdr->ldp_hdr.msg_type == MSG_T_RG_APP_DATA) { /* Process receive APP info*/ mlacp_sync_receiver_handler(csm, msg); @@ -1084,9 +1097,9 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) len = mlacp_prepare_for_sync_request_tlv(csm, g_csm_buf, CSM_BUFFER_SIZE); iccp_csm_send(csm, g_csm_buf, len); } - + /* Send system config*/ - if (MLACP(csm).system_config_changed != 0) + if (MLACP(csm).system_config_changed != 0) { memset(g_csm_buf, 0, CSM_BUFFER_SIZE); len = mlacp_prepare_for_sys_config(csm, g_csm_buf, CSM_BUFFER_SIZE); @@ -1095,44 +1108,44 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) memset(g_csm_buf, 0, CSM_BUFFER_SIZE); len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); iccp_csm_send(csm, g_csm_buf, len); - + MLACP(csm).system_config_changed = 0; } - + /* Send mlag purge lif*/ LIST_FOREACH(lif_purge, &(MLACP(csm).lif_purge_list), mlacp_purge_next) { /* Purge info*/ memset(g_csm_buf, 0, CSM_BUFFER_SIZE); - len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif_purge,1); + len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif_purge, 1); iccp_csm_send(csm, g_csm_buf, len); /* Destroy old interface*/ if (lif_purge != NULL) LIST_REMOVE(lif_purge, mlacp_purge_next); } - + /* Send mlag lif*/ LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) { - if (lif->type == IF_T_PORT_CHANNEL && lif->port_config_sync) + if (lif->type == IF_T_PORT_CHANNEL && lif->port_config_sync) { /* Send port channel information*/ memset(g_csm_buf, 0, CSM_BUFFER_SIZE); - len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif,0); + len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif, 0); iccp_csm_send(csm, g_csm_buf, len); memset(g_csm_buf, 0, CSM_BUFFER_SIZE); len = mlacp_prepare_for_port_channel_info(csm, g_csm_buf, CSM_BUFFER_SIZE, lif); - iccp_csm_send(csm, g_csm_buf, len); - + iccp_csm_send(csm, g_csm_buf, len); + lif->port_config_sync = 0; } - + /*send if portchannel state change */ - if (lif->type == IF_T_PORT_CHANNEL && lif->changed) - { + if (lif->type == IF_T_PORT_CHANNEL && lif->changed) + { /* Send port channel state information*/ - memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, lif); iccp_csm_send(csm, g_csm_buf, len); lif->changed = 0; @@ -1141,15 +1154,15 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) /* Send MAC info if any*/ mlacp_sync_send_syncMacInfo(csm); - + /* Send ARP info if any*/ mlacp_sync_send_syncArpInfo(csm); /*If peer is warm reboot*/ - if(csm->peer_warm_reboot_time != 0) + if (csm->peer_warm_reboot_time != 0) { /*Peer warm reboot timeout, recover to normal reboot*/ - if((time(NULL) - csm->peer_warm_reboot_time) >= 90) + if ((time(NULL) - csm->peer_warm_reboot_time) >= 90) csm->peer_warm_reboot_time = 0; } diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index 902723f7c147..45d442a48a97 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -1,26 +1,26 @@ /* -* mlacp_link_handler.c -* mLACP link handler -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * mlacp_link_handler.c + * mLACP link handler + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -43,7 +43,8 @@ * Enum * * ***************************************/ -typedef enum route_manipulate_type { +typedef enum route_manipulate_type +{ ROUTE_NONE, ROUTE_ADD, ROUTE_DEL @@ -63,191 +64,191 @@ char g_ipv4_str[INET_ADDRSTRLEN]; char *show_ip_str(uint32_t ipv4_addr) { struct in_addr in_addr; - - memset(g_ipv4_str, 0 ,sizeof(g_ipv4_str)); + + memset(g_ipv4_str, 0, sizeof(g_ipv4_str)); in_addr.s_addr = ipv4_addr; inet_ntop(AF_INET, &in_addr, g_ipv4_str, INET_ADDRSTRLEN); - + return g_ipv4_str; } - static int getHwAddr(char *buff, char *mac) - { - int i = 0; - unsigned int p[6]; - - if( buff == NULL || mac == NULL ) - { - return -1; - } - - if(sscanf(mac, "%x:%x:%x:%x:%x:%x", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]) < 6) - { - return -1; - } - - for(i = 0; i < 6; i ++) - { - buff[i] = p[i]; - } - - return 0; - } - - /* Set an entry in the ARP cache. */ +static int getHwAddr(char *buff, char *mac) +{ + int i = 0; + unsigned int p[6]; + + if ( buff == NULL || mac == NULL ) + { + return -1; + } + + if (sscanf(mac, "%x:%x:%x:%x:%x:%x", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]) < 6) + { + return -1; + } + + for (i = 0; i < 6; i++) + { + buff[i] = p[i]; + } + + return 0; +} + +/* Set an entry in the ARP cache. */ int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac) { - struct arpreq arpreq; - struct sockaddr_in *sin; - struct in_addr ina; - int flags; - int rc; - int sock_fd = 0; - - ICCPD_LOG_DEBUG(__FUNCTION__, "Set arp entry for IP:%s MAC:%s ifname:%s\n", show_ip_str(htonl(ip)), mac,ifname); - - if(ifname == NULL || ip == 0 || mac == NULL) - { - return -1; - } - - /*you must add this becasue some system will return "Invlid argument" - because some argument isn't zero */ - memset(&arpreq, 0, sizeof(struct arpreq)); - sin = (struct sockaddr_in *) &arpreq.arp_pa; - memset(sin, 0, sizeof(struct sockaddr_in)); - sin->sin_family = AF_INET; - ina.s_addr = htonl(ip); - memcpy(&sin->sin_addr, (char *) &ina, sizeof(struct in_addr)); - - if(getHwAddr((char *)arpreq.arp_ha.sa_data, mac) < 0) - { - return -1; - } - - strncpy(arpreq.arp_dev, ifname, 15); - - flags = ATF_COM; //note, must set flag, if not,you will get error - - arpreq.arp_flags = flags; - - sock_fd = socket(AF_INET, SOCK_DGRAM, 0); - if(sock_fd < 0) - { - return -1; - } - - rc = ioctl(sock_fd, SIOCSARP, &arpreq); - if (rc < 0) - { - close(sock_fd); - return -1; - } - - close(sock_fd); - - return 0; + struct arpreq arpreq; + struct sockaddr_in *sin; + struct in_addr ina; + int flags; + int rc; + int sock_fd = 0; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Set arp entry for IP:%s MAC:%s ifname:%s\n", show_ip_str(htonl(ip)), mac, ifname); + + if (ifname == NULL || ip == 0 || mac == NULL) + { + return -1; + } + + /*you must add this becasue some system will return "Invlid argument" + because some argument isn't zero */ + memset(&arpreq, 0, sizeof(struct arpreq)); + sin = (struct sockaddr_in *)&arpreq.arp_pa; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + ina.s_addr = htonl(ip); + memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr)); + + if (getHwAddr((char *)arpreq.arp_ha.sa_data, mac) < 0) + { + return -1; + } + + strncpy(arpreq.arp_dev, ifname, 15); + + flags = ATF_COM; //note, must set flag, if not,you will get error + + arpreq.arp_flags = flags; + + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) + { + return -1; + } + + rc = ioctl(sock_fd, SIOCSARP, &arpreq); + if (rc < 0) + { + close(sock_fd); + return -1; + } + + close(sock_fd); + + return 0; } - /* Delete an entry from the ARP cache. */ +/* Delete an entry from the ARP cache. */ int mlacp_fsm_arp_del(char *ifname, uint32_t ip) { - struct arpreq arpreq; - struct sockaddr_in *sin; - struct in_addr ina; - int rc; - int sock_fd = 0; - - ICCPD_LOG_DEBUG(__FUNCTION__,"%s: Del arp entry for IP : %s\n", __FUNCTION__, show_ip_str(htonl(ip))); - - if(ifname == NULL || ip == 0) - { - return -1; - } - - /*you must add this becasue some system will return "Invlid argument" - because some argument isn't zero */ - memset(&arpreq, 0, sizeof(struct arpreq)); - - sin = (struct sockaddr_in *) &arpreq.arp_pa; - memset(sin, 0, sizeof(struct sockaddr_in)); - sin->sin_family = AF_INET; - ina.s_addr = htonl(ip); - memcpy(&sin->sin_addr, (char *) &ina, sizeof(struct in_addr)); - - strncpy(arpreq.arp_dev, ifname, 15); - - sock_fd = socket(AF_INET, SOCK_DGRAM, 0); - if(sock_fd < 0) - { - return -1; - } - - rc = ioctl(sock_fd, SIOCDARP, &arpreq); - if (rc < 0) - { - close(sock_fd); - return -1; - } - - close(sock_fd); - - return 0; - } - + struct arpreq arpreq; + struct sockaddr_in *sin; + struct in_addr ina; + int rc; + int sock_fd = 0; + + ICCPD_LOG_DEBUG(__FUNCTION__, "%s: Del arp entry for IP : %s\n", __FUNCTION__, show_ip_str(htonl(ip))); + + if (ifname == NULL || ip == 0) + { + return -1; + } + + /*you must add this becasue some system will return "Invlid argument" + because some argument isn't zero */ + memset(&arpreq, 0, sizeof(struct arpreq)); + + sin = (struct sockaddr_in *)&arpreq.arp_pa; + memset(sin, 0, sizeof(struct sockaddr_in)); + sin->sin_family = AF_INET; + ina.s_addr = htonl(ip); + memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr)); + + strncpy(arpreq.arp_dev, ifname, 15); + + sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) + { + return -1; + } + + rc = ioctl(sock_fd, SIOCDARP, &arpreq); + if (rc < 0) + { + close(sock_fd); + return -1; + } + + close(sock_fd); + + return 0; +} + static int arp_set_handler(struct CSM* csm, - struct LocalInterface* lif, - int add) + struct LocalInterface* lif, + int add) { struct Msg* msg = NULL; struct ARPMsg* arp_msg = NULL; char mac_str[18] = ""; - + if (!csm || !lif) return 0; - + if (add) goto add_arp; else goto del_arp; - + /* Process Add */ -add_arp: + add_arp: if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return 0; - + TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { mac_str[0] = '\0'; - arp_msg = (struct ARPMsg*) msg->buf; - + arp_msg = (struct ARPMsg*)msg->buf; + /* only process add*/ if (arp_msg->op_type == ARP_SYNC_DEL) continue; - + /* find the ARP for lif_list*/ if (strcmp(lif->name, arp_msg->ifname) != 0) continue; sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], - arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); - + arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); + mlacp_fsm_arp_set(arp_msg->ifname, arp_msg->ipv4_addr, mac_str); ICCPD_LOG_DEBUG(__FUNCTION__, "Add dynamic ARP to kernel [%s]", show_ip_str(htonl(arp_msg->ipv4_addr))); } goto done; - -del_arp: + + del_arp: /* Process Del */ TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { - arp_msg = (struct ARPMsg*) msg->buf; - + arp_msg = (struct ARPMsg*)msg->buf; + /* find the ARP for lif_list*/ if (strcmp(lif->name, arp_msg->ifname) != 0) continue; - + /* don't process del*/ if (arp_msg->op_type == ARP_SYNC_DEL) continue; @@ -258,14 +259,14 @@ static int arp_set_handler(struct CSM* csm, show_ip_str(htonl(arp_msg->ipv4_addr))); } -done: + done: return 0; } /***************************************** -* Port-Channel Status Handler -* -****************************************/ + * Port-Channel Status Handler + * + ****************************************/ static void set_route_by_linux_route(struct CSM* csm, struct LocalInterface *local_if, int is_add) @@ -281,52 +282,52 @@ static void set_route_by_linux_route(struct CSM* csm, /* enable kernel forwarding support*/ system("echo 1 > /proc/sys/net/ipv4/ip_forward"); - if(!csm || !local_if) + if (!csm || !local_if) return; sprintf(ipv4_dest_str, "%s", show_ip_str(htonl(local_if->ipv4_addr))); - ptr=strrchr(ipv4_dest_str, '.');strcpy(ptr, ".0\0"); + ptr = strrchr(ipv4_dest_str, '.'); strcpy(ptr, ".0\0"); #if 1 /* set gw route*/ /*sprintf(syscmd, "ip route %s %s/%d proto static metric 200 nexthop via %s > /dev/null 2>&1",*/ sprintf(syscmd, "ip route %s %s/%d metric 200 nexthop via %s > /dev/null 2>&1", - (is_add)?"add":"del", ipv4_dest_str, local_if->prefixlen, + (is_add) ? "add" : "del", ipv4_dest_str, local_if->prefixlen, csm->peer_ip); #else // set interface route sprintf(syscmd, "route %s -net %s/%d %s > /dev/null 2>&1", - (is_add)?"add":"del", ipv4_dest_str, local_if->prefixlen, + (is_add) ? "add" : "del", ipv4_dest_str, local_if->prefixlen, local_if->name); #endif ret = system(syscmd); - ICCPD_LOG_DEBUG(__FUNCTION__, " %s ret = %d", syscmd,ret); + ICCPD_LOG_DEBUG(__FUNCTION__, " %s ret = %d", syscmd, ret); return; } static void update_vlan_if_info(struct CSM *csm, - struct LocalInterface *local_if, - struct LocalInterface *vlan_if, - int po_state) + struct LocalInterface *local_if, + struct LocalInterface *vlan_if, + int po_state) { if (!csm || !local_if || !vlan_if) return; - + vlan_if->mlacp_state = MLACP(csm).current_state; return; } static void update_l3_if_info(struct CSM *csm, - struct LocalInterface *local_if, + struct LocalInterface *local_if, struct LocalInterface *l3_if, int po_state) { if (!csm || !l3_if) return; - + l3_if->mlacp_state = MLACP(csm).current_state; return; @@ -338,12 +339,12 @@ static void update_po_if_info(struct CSM *csm, { if (!csm || !local_if) return; - + /* update local po info*/ - if(local_if->po_active != po_state) + if (local_if->po_active != po_state) { local_if->changed = 1; - local_if->po_active = (po_state!=0); + local_if->po_active = (po_state != 0); /*printf("update po [%s=%d]\n",local_if->name, local_if->po_active);*/ } local_if->mlacp_state = MLACP(csm).current_state; @@ -357,16 +358,16 @@ static void set_l3_itf_state(struct CSM *csm, { if (!csm || !set_l3_local_if) return; - + if (set_l3_local_if && (route_type != ROUTE_NONE)) { /*set_default_route(csm);*/ - ICCPD_LOG_DEBUG(__FUNCTION__, " route set Interface = %s route type = %d route = %s nexthop via = %s ", - set_l3_local_if->name, route_type, show_ip_str(htonl(set_l3_local_if->ipv4_addr)), csm->peer_ip ); - + ICCPD_LOG_DEBUG(__FUNCTION__, " route set Interface = %s route type = %d route = %s nexthop via = %s ", + set_l3_local_if->name, route_type, show_ip_str(htonl(set_l3_local_if->ipv4_addr)), csm->peer_ip ); + /* set static route*/ - if(route_type == ROUTE_ADD) + if (route_type == ROUTE_ADD) { /*set_route_by_linux_route(csm, set_l3_local_if, 1);*/ /*add static route by linux route tool*/ /*If the L3 intf is not Vlan, del ARP; else wait ARP age*/ @@ -375,7 +376,7 @@ static void set_l3_itf_state(struct CSM *csm, arp_set_handler(csm, set_l3_local_if, 0); /* del arp*/ } } - else if(route_type == ROUTE_DEL) + else if (route_type == ROUTE_DEL) { /*set_route_by_linux_route(csm, set_l3_local_if, 0);*/ /*del static route by linux route tool*/ arp_set_handler(csm, set_l3_local_if, 1); /* add arp*/ @@ -389,117 +390,117 @@ static int peer_po_is_alive(struct CSM *csm, int po_ifindex) { struct PeerInterface *pif = NULL; int pif_active = 0; - + if (!csm) return 0; - + LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) { - if(pif->type != IF_T_PORT_CHANNEL) + if (pif->type != IF_T_PORT_CHANNEL) continue; - if(pif->po_id!= po_ifindex) + if (pif->po_id != po_ifindex) continue; - - if(pif->po_active) + + if (pif->po_active) pif_active = 1; /*pif alive*/ break; } - + return pif_active; } -static void mlacp_clean_fdb (void) +static void mlacp_clean_fdb(void) { struct IccpSyncdHDr * msg_hdr; char *msg_buf = g_csm_buf; struct System *sys; - + sys = system_get_instance(); - if(sys == NULL) + if (sys == NULL) return; memset(msg_buf, 0, CSM_BUFFER_SIZE); msg_hdr = (struct IccpSyncdHDr *)msg_buf; - msg_hdr->ver= 1; + msg_hdr->ver = 1; msg_hdr->type = MCLAG_MSG_TYPE_FLUSH_FDB; - msg_hdr->len = sizeof(struct IccpSyncdHDr); + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + if (sys->sync_fd) + write(sys->sync_fd, msg_buf, msg_hdr->len); - if(sys->sync_fd) - write(sys->sync_fd,msg_buf, msg_hdr->len); - - ICCPD_LOG_DEBUG(__FUNCTION__, "notify mclagsyncd clear fdb"); + ICCPD_LOG_DEBUG(__FUNCTION__, "notify mclagsyncd clear fdb"); return; } -void set_peerlink_mlag_port_learn (struct LocalInterface *lif, int enable) +void set_peerlink_mlag_port_learn(struct LocalInterface *lif, int enable) { struct IccpSyncdHDr * msg_hdr; mclag_sub_option_hdr_t * sub_msg; char *msg_buf = g_csm_buf; int msg_len; struct System *sys; - + sys = system_get_instance(); - if(sys == NULL) - return; + if (sys == NULL) + return; if (!lif) return; - memset(msg_buf, 0, CSM_BUFFER_SIZE); + memset(msg_buf, 0, CSM_BUFFER_SIZE); msg_hdr = (struct IccpSyncdHDr *)msg_buf; - msg_hdr->ver= 1; + msg_hdr->ver = 1; msg_hdr->type = MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE; - - msg_hdr->len = sizeof(struct IccpSyncdHDr); - - sub_msg =(mclag_sub_option_hdr_t*) &msg_buf[msg_hdr->len]; - sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE; - - if(enable) + + msg_hdr->len = sizeof(struct IccpSyncdHDr); + + sub_msg = (mclag_sub_option_hdr_t*)&msg_buf[msg_hdr->len]; + sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE; + + if (enable) sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE; - + msg_len = strlen(lif->name); - memcpy(sub_msg->data, lif->name, msg_len); - + memcpy(sub_msg->data, lif->name, msg_len); + sub_msg->op_len = msg_len; - msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); msg_hdr->len += sub_msg->op_len; - + ICCPD_LOG_DEBUG(__FUNCTION__, " send port-learn msg to sync for %s , member %s", - lif->name, sub_msg->data); + lif->name, sub_msg->data); /*send msg*/ - if(sys->sync_fd) - write(sys->sync_fd,msg_buf, msg_hdr->len); + if (sys->sync_fd) + write(sys->sync_fd, msg_buf, msg_hdr->len); return; } -static void set_peerlink_mlag_port_kernel_forward ( +static void set_peerlink_mlag_port_kernel_forward( struct CSM *csm, struct LocalInterface *lif, int enable) { if (!csm || !csm->peer_link_if || !lif) return; - - char cmd[256] = {0}; - + + char cmd[256] = { 0 }; + sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP", "-D", csm->peer_link_if->name, lif->name); - ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s",cmd ); + ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s", cmd ); system(cmd); sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP", - (enable)?"-A":"-D", csm->peer_link_if->name, lif->name); - ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s",cmd ); + (enable) ? "-A" : "-D", csm->peer_link_if->name, lif->name); + ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s", cmd ); system(cmd); return; } -void update_peerlink_isolate_from_all_csm_lif ( +void update_peerlink_isolate_from_all_csm_lif( struct CSM* csm) { struct LocalInterface *lif = NULL; @@ -509,19 +510,20 @@ void update_peerlink_isolate_from_all_csm_lif ( struct System *sys; char mlag_po_buf[512]; - int src_len = 0,dst_len =0; + int src_len = 0, dst_len = 0; sys = system_get_instance(); - if(sys == NULL) - return; - - if (!csm || !csm->peer_link_if) return; - - memset(msg_buf,0,4095); - memset(mlag_po_buf,0, 511); - + if (sys == NULL) + return; + + if (!csm || !csm->peer_link_if) + return; + + memset(msg_buf, 0, 4095); + memset(mlag_po_buf, 0, 511); + msg_hdr = (struct IccpSyncdHDr *)msg_buf; - msg_hdr->ver= 1; + msg_hdr->ver = 1; msg_hdr->type = MCLAG_MSG_TYPE_PORT_ISOLATE; msg_hdr->len = sizeof(struct IccpSyncdHDr); @@ -529,7 +531,7 @@ void update_peerlink_isolate_from_all_csm_lif ( sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_ISOLATE_SRC; - if(csm->peer_link_if->type == IF_T_VXLAN) + if (csm->peer_link_if->type == IF_T_VXLAN) { /*TBD: vxlan tunnel port isolation will be supportted later*/ return; @@ -538,77 +540,77 @@ void update_peerlink_isolate_from_all_csm_lif ( /*VTTNL0001;Ethernet0001,Ethernet0002*/ /*src_len= strlen(csm->peer_link_if->name); */ - src_len += snprintf(src_buf+src_len, sizeof(src_buf)-src_len, "%s", csm->peer_link_if->name); - src_len += snprintf(src_buf+src_len, sizeof(src_buf)-src_len, "%s",";"); - + src_len += snprintf(src_buf + src_len, sizeof(src_buf) - src_len, "%s", csm->peer_link_if->name); + src_len += snprintf(src_buf + src_len, sizeof(src_buf) - src_len, "%s", ";"); + /*traverse all ethernet port */ LIST_FOREACH(lif, &(sys->lif_list), system_next) { - if(lif->type !=IF_T_PORT) + if (lif->type != IF_T_PORT) continue; - + /* need to isolate port, get it's name */ - if(begin_eth_port != 0) + if (begin_eth_port != 0) { - src_len += snprintf(src_buf+src_len, sizeof(src_buf)-src_len, "%s",","); + src_len += snprintf(src_buf + src_len, sizeof(src_buf) - src_len, "%s", ","); } - - src_len += snprintf(src_buf+src_len, sizeof(src_buf)-src_len, "%s", lif->name); + + src_len += snprintf(src_buf + src_len, sizeof(src_buf) - src_len, "%s", lif->name); begin_eth_port = 1; } memcpy(sub_msg->data, src_buf, src_len); - ICCPD_LOG_DEBUG(__FUNCTION__, "isolate src %s, data %s, len %d",src_buf, sub_msg->data, src_len); + ICCPD_LOG_DEBUG(__FUNCTION__, "isolate src %s, data %s, len %d", src_buf, sub_msg->data, src_len); #endif } else { - src_len= strlen(csm->peer_link_if->name); - memcpy(sub_msg->data, csm->peer_link_if->name, src_len); + src_len = strlen(csm->peer_link_if->name); + memcpy(sub_msg->data, csm->peer_link_if->name, src_len); } sub_msg->op_len = src_len; /*sub msg dst */ msg_hdr->len += sub_msg->op_len; - msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); sub_msg = (mclag_sub_option_hdr_t *)&msg_buf[msg_hdr->len]; sub_msg->op_type = MCLAG_SUB_OPTION_TYPE_ISOLATE_DST; /*traverse all portchannel member port and send msg to syncd */ LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) { - if(lif->type !=IF_T_PORT_CHANNEL) + if (lif->type != IF_T_PORT_CHANNEL) continue; - - /* check pif port state and lif pochannel state */ - if(lif->isolate_to_peer_link == 1) - { - /* need to isolate port, get it's member name */ - if(strlen(mlag_po_buf) != 0) - dst_len += snprintf(mlag_po_buf+dst_len, sizeof(mlag_po_buf)-dst_len, "%s",","); - - dst_len += snprintf(mlag_po_buf+dst_len, sizeof(mlag_po_buf)-dst_len, "%s", lif->portchannel_member_buf); - } - } - + + /* check pif port state and lif pochannel state */ + if (lif->isolate_to_peer_link == 1) + { + /* need to isolate port, get it's member name */ + if (strlen(mlag_po_buf) != 0) + dst_len += snprintf(mlag_po_buf + dst_len, sizeof(mlag_po_buf) - dst_len, "%s", ","); + + dst_len += snprintf(mlag_po_buf + dst_len, sizeof(mlag_po_buf) - dst_len, "%s", lif->portchannel_member_buf); + } + } + sub_msg->op_len = dst_len; - msg_hdr->len += sizeof(mclag_sub_option_hdr_t); - msg_hdr->len += sub_msg->op_len; - - if(dst_len) + msg_hdr->len += sizeof(mclag_sub_option_hdr_t); + msg_hdr->len += sub_msg->op_len; + + if (dst_len) { memcpy(sub_msg->data, mlag_po_buf, dst_len); - ICCPD_LOG_DEBUG(__FUNCTION__, "isolate dst %s, data %s, len %d",mlag_po_buf, sub_msg->data, dst_len); + ICCPD_LOG_DEBUG(__FUNCTION__, "isolate dst %s, data %s, len %d", mlag_po_buf, sub_msg->data, dst_len); } /*send msg*/ - if(sys->sync_fd) - write(sys->sync_fd,msg_buf, msg_hdr->len); - + if (sys->sync_fd) + write(sys->sync_fd, msg_buf, msg_hdr->len); + return; } -static void set_peerlink_mlag_port_isolate ( +static void set_peerlink_mlag_port_isolate( struct CSM *csm, struct LocalInterface *lif, int enable) @@ -616,39 +618,40 @@ static void set_peerlink_mlag_port_isolate ( if (!csm || !csm->peer_link_if || !lif) return; - if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; - + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + lif->isolate_to_peer_link = enable; - + update_peerlink_isolate_from_all_csm_lif(csm); csm->isolate_update_time = time(NULL); - + /* Kernel also needs to block traffic from peerlink to mlag-port*/ set_peerlink_mlag_port_kernel_forward(csm, lif, enable); - + return; } void peerlink_port_isolate_cleanup(struct CSM* csm) { - struct LocalInterface *local_if=NULL; - + struct LocalInterface *local_if = NULL; + if (!csm) return; /* Clean all port block*/ LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) { - if(local_if->type == IF_T_PORT_CHANNEL) + if (local_if->type == IF_T_PORT_CHANNEL) { set_peerlink_mlag_port_isolate(csm, local_if, 0); } } - + return; } -void update_peerlink_isolate_from_pif ( +void update_peerlink_isolate_from_pif( struct CSM *csm, struct PeerInterface *pif, int pif_po_state, @@ -656,50 +659,53 @@ void update_peerlink_isolate_from_pif ( { struct LocalInterface *lif = NULL; int lif_po_state = 1; - - if(!csm || !csm->peer_link_if || !pif) return; - if(new_create == 0 && pif_po_state == pif->po_active) return; - if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; - + + if (!csm || !csm->peer_link_if || !pif) + return; + if (new_create == 0 && pif_po_state == pif->po_active) + return; + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + /* peer link changed*/ LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) { - if(strcmp(lif->name, pif->name)!=0) + if (strcmp(lif->name, pif->name) != 0) continue; - + lif_po_state = lif->po_active; break; } - - if (!lif) + + if (!lif) { ICCPD_LOG_DEBUG(__FUNCTION__, "can't find lif"); return; } - + ICCPD_LOG_DEBUG(__FUNCTION__, " from peer %s local(%s) / peer(%s)", - lif->name, - (lif_po_state) ? "up" : "down", - (pif_po_state) ? "up" : "down"); - - if (lif_po_state == 1) + lif->name, + (lif_po_state) ? "up" : "down", + (pif_po_state) ? "up" : "down"); + + if (lif_po_state == 1) { - if (pif_po_state == 1) + if (pif_po_state == 1) { /* both peer-pair link up, enable port-isolate*/ ICCPD_LOG_DEBUG(__FUNCTION__, " Enable port-isolate from %s to %s", - csm->peer_link_if->name, lif->name); + csm->peer_link_if->name, lif->name); set_peerlink_mlag_port_isolate(csm, lif, 1); } - else + else { /* local link up, and peer link changes to down, disable port-isolate*/ ICCPD_LOG_DEBUG(__FUNCTION__, "Disable port-isolate from %s to %s", - csm->peer_link_if->name, lif->name); + csm->peer_link_if->name, lif->name); set_peerlink_mlag_port_isolate(csm, lif, 0); } } - else + else { ;/* local link down, do nothing*/ } @@ -707,49 +713,51 @@ void update_peerlink_isolate_from_pif ( return; } -static void update_peerlink_isolate_from_lif ( +static void update_peerlink_isolate_from_lif( struct CSM* csm, struct LocalInterface* lif, int lif_po_state) { struct PeerInterface *pif = NULL; int pif_po_state = 1; - - if (!csm || !csm->peer_link_if || !lif) return; + + if (!csm || !csm->peer_link_if || !lif) + return; /*if (lif_po_state == lif->po_active) return;*/ - if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; - + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + /* local link changed*/ LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) { - if (strcmp(pif->name, lif->name)!=0) + if (strcmp(pif->name, lif->name) != 0) continue; - + pif_po_state = pif->po_active; break; } - + ICCPD_LOG_DEBUG(__FUNCTION__, " from local %s local(%s) / peer(%s)", - lif->name,(lif_po_state) ? "up" : "down", (pif_po_state) ? "up" : "down"); - - if (lif_po_state == 1) + lif->name, (lif_po_state) ? "up" : "down", (pif_po_state) ? "up" : "down"); + + if (lif_po_state == 1) { - if (pif_po_state == 1) + if (pif_po_state == 1) { /* both peer-pair link up, enable port-isolate*/ ICCPD_LOG_DEBUG(__FUNCTION__, "Enable port-isolate from %s to %s", - csm->peer_link_if->name, lif->name); + csm->peer_link_if->name, lif->name); set_peerlink_mlag_port_isolate(csm, lif, 1); } - else + else { /* peer link down, local link changes to up, disable port-isolate*/ ICCPD_LOG_DEBUG(__FUNCTION__, " Disable port-isolate from %s to %s", - csm->peer_link_if->name, lif->name); + csm->peer_link_if->name, lif->name); set_peerlink_mlag_port_isolate(csm, lif, 0); } - } - else + } + else { ;/* local link down, do nothing*/ } @@ -761,33 +769,33 @@ static void update_l2_po_state(struct CSM *csm, struct LocalInterface *lif, int po_state) { - ROUTE_MANIPULATE_TYPE_E route_type=ROUTE_NONE; - struct VLAN_ID *vlan=NULL; - struct LocalInterface *set_l3_vlan_if=NULL; - + ROUTE_MANIPULATE_TYPE_E route_type = ROUTE_NONE; + struct VLAN_ID *vlan = NULL; + struct LocalInterface *set_l3_vlan_if = NULL; + if (!csm || !lif) return; - + /*L2 po*/ /*if (po_state != lif->po_active && po_state == 0) - { + { mlacp_clean_fdb(); - }*/ - + }*/ + /*Is there any L3 vlan over L2 po?*/ LIST_FOREACH(vlan, &(lif->vlan_list), port_next) { route_type = ROUTE_NONE; - - if(!vlan->vlan_itf) + + if (!vlan->vlan_itf) continue; - + /* If the po is under a vlan, update vlan state first*/ update_vlan_if_info(csm, lif, vlan->vlan_itf, po_state); - - if(!local_if_is_l3_mode(vlan->vlan_itf)) + + if (!local_if_is_l3_mode(vlan->vlan_itf)) continue; - + /*NOTE * assume only one mlag per vlan * need to add rules for per mlag per vlan later (arp list?) @@ -796,18 +804,18 @@ static void update_l2_po_state(struct CSM *csm, if (po_state != lif->po_active || MLACP(csm).current_state != set_l3_vlan_if->mlacp_state) { - if(po_state==1) + if (po_state == 1) { route_type = ROUTE_DEL; } - else if(po_state == 0 - && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + else if (po_state == 0 + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { if (peer_po_is_alive(csm, lif->ifindex) == 1) route_type = ROUTE_ADD; } } - + /*update_po_arp_list(csm, set_l3_vlan_if);*/ set_l3_itf_state(csm, set_l3_vlan_if, route_type); update_l3_if_info(csm, lif, set_l3_vlan_if, po_state); @@ -820,37 +828,38 @@ static void update_l3_po_state(struct CSM *csm, struct LocalInterface *lif, int po_state) { - ROUTE_MANIPULATE_TYPE_E route_type=ROUTE_NONE; - struct LocalInterface *set_l3_lif=NULL; + ROUTE_MANIPULATE_TYPE_E route_type = ROUTE_NONE; + struct LocalInterface *set_l3_lif = NULL; + /*L3 po*/ set_l3_lif = lif; - + if (!csm || !lif) return; - - if(po_state != lif->po_active + + if (po_state != lif->po_active && po_state == 1) { /* po alive, clean static route & recover the ARP*/ route_type = ROUTE_DEL; } - else if(po_state != lif->po_active - && po_state == 0 - && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + else if (po_state != lif->po_active + && po_state == 0 + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /* po is not alive & peer-link alive, set static route*/ if (peer_po_is_alive(csm, lif->po_id) == 1) route_type = ROUTE_ADD; } - else if(MLACP(csm).current_state != lif->mlacp_state - && MLACP(csm).current_state == MLACP_STATE_EXCHANGE - && po_state == 0) + else if (MLACP(csm).current_state != lif->mlacp_state + && MLACP(csm).current_state == MLACP_STATE_EXCHANGE + && po_state == 0) { /* when peer-pair link ready, set static route for broken po link*/ if (peer_po_is_alive(csm, lif->po_id) == 1) route_type = ROUTE_ADD; } - + /*update_po_arp_list(csm, set_l3_lif);*/ set_l3_itf_state(csm, set_l3_lif, route_type); update_l3_if_info(csm, lif, set_l3_lif, po_state); @@ -858,12 +867,12 @@ static void update_l3_po_state(struct CSM *csm, return; } -int is_local_vlan_on(struct VLAN_ID* vlan_id_list) -{ - if(!vlan_id_list->vlan_itf) - return 0; - - return 1; +int is_local_vlan_on(struct VLAN_ID* vlan_id_list) +{ + if (!vlan_id_list->vlan_itf) + return 0; + + return 1; } void syn_arp_info_to_peer(struct CSM *csm, struct LocalInterface *local_if) @@ -872,28 +881,28 @@ void syn_arp_info_to_peer(struct CSM *csm, struct LocalInterface *local_if) struct ARPMsg *arp_msg = NULL, *arp_info = NULL; struct Msg *msg_send = NULL; - if(!csm || !local_if) + if (!csm || !local_if) return; - - if(!TAILQ_EMPTY(&(MLACP(csm).arp_list))) + + if (!TAILQ_EMPTY(&(MLACP(csm).arp_list))) { TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { - arp_info = (struct ARPMsg*) msg->buf; - - if(strcmp(arp_info->ifname, local_if->name)!=0) + arp_info = (struct ARPMsg*)msg->buf; + + if (strcmp(arp_info->ifname, local_if->name) != 0) continue; - - arp_msg = (struct ARPMsg*) msg->buf; + + arp_msg = (struct ARPMsg*)msg->buf; arp_msg->op_type = ARP_SYNC_ADD; - + if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); ICCPD_LOG_DEBUG( __FUNCTION__, "Enqueue ARP[ADD] for %s", - show_ip_str(htonl(arp_msg->ipv4_addr))); + show_ip_str(htonl(arp_msg->ipv4_addr))); } - else + else ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } @@ -906,21 +915,21 @@ void update_stp_peer_link(struct CSM *csm, struct PeerInterface *pif, int po_state, int new_create) { - struct LocalInterface *lif=NULL; - struct VLAN_ID *vlan=NULL; - - if(!csm || !pif) + struct LocalInterface *lif = NULL; + struct VLAN_ID *vlan = NULL; + + if (!csm || !pif) return; - if(new_create == 0 && po_state == pif->po_active) + if (new_create == 0 && po_state == pif->po_active) return; - + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) { - if(strcmp(lif->name, pif->name)!=0) + if (strcmp(lif->name, pif->name) != 0) continue; - + /* update lif route if pif link status changes */ - if (local_if_is_l3_mode(lif)) + if (local_if_is_l3_mode(lif)) { if (po_state == 1 && lif->po_active == 0) set_l3_itf_state(csm, lif, ROUTE_ADD); @@ -933,32 +942,32 @@ void update_stp_peer_link(struct CSM *csm, syn_arp_info_to_peer(csm, lif); } } - else + else { LIST_FOREACH(vlan, &(lif->vlan_list), port_next) { - if(!is_local_vlan_on(vlan)) + if (!is_local_vlan_on(vlan)) continue; - if(!local_if_is_l3_mode(vlan->vlan_itf)) + if (!local_if_is_l3_mode(vlan->vlan_itf)) continue; - + /*NOTE - * assume only one mlag per bridge - * need to add rules for per mlag per bridge later (arp list?) - */ + * assume only one mlag per bridge + * need to add rules for per mlag per bridge later (arp list?) + */ if (po_state == 1 && lif->po_active == 0) set_l3_itf_state(csm, vlan->vlan_itf, ROUTE_ADD); else if (po_state == 0 && lif->po_active == 0) set_l3_itf_state(csm, vlan->vlan_itf, ROUTE_DEL); - /*If pif change to active, and local is also active, syn arp to peer*/ + /*If pif change to active, and local is also active, syn arp to peer*/ if (po_state == 1 && lif->po_active == 1) { syn_arp_info_to_peer(csm, vlan->vlan_itf); } } } - + break; } @@ -972,27 +981,27 @@ void iccp_get_fdb_change_from_syncd( void) struct System *sys; sys = system_get_instance(); - if(sys == NULL) + if (sys == NULL) return; memset(msg_buf, 0, CSM_BUFFER_SIZE); msg_hdr = (struct IccpSyncdHDr *)msg_buf; - msg_hdr->ver= 1; + msg_hdr->ver = 1; msg_hdr->type = MCLAG_MSG_TYPE_GET_FDB_CHANGES; - msg_hdr->len = sizeof(struct IccpSyncdHDr); - + msg_hdr->len = sizeof(struct IccpSyncdHDr); + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d write get fdb change msg ", - sys->sync_fd); - + sys->sync_fd); + /*send msg*/ - if(sys->sync_fd > 0) - write(sys->sync_fd,msg_buf, msg_hdr->len); + if (sys->sync_fd > 0) + write(sys->sync_fd, msg_buf, msg_hdr->len); return; } -void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg,uint8_t mac_type) +void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg, uint8_t mac_type) { struct IccpSyncdHDr * msg_hdr; char *msg_buf = g_csm_buf; @@ -1000,30 +1009,30 @@ void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg,uint8_t mac_type) struct mclag_fdb_info * mac_info; sys = system_get_instance(); - if(sys == NULL) - return; + if (sys == NULL) + return; memset(msg_buf, 0, CSM_BUFFER_SIZE); msg_hdr = (struct IccpSyncdHDr *)msg_buf; - msg_hdr->ver= 1; + msg_hdr->ver = 1; msg_hdr->type = MCLAG_MSG_TYPE_SET_FDB; /*mac msg */ mac_info = (struct mclag_fdb_info *)&msg_buf[sizeof(struct IccpSyncdHDr)]; mac_info->vid = mac_msg->vid; - memcpy(mac_info->port_name,mac_msg->ifname,MAX_L_PORT_NAME); - memcpy(mac_info->mac ,mac_msg->mac_str,32); + memcpy(mac_info->port_name, mac_msg->ifname, MAX_L_PORT_NAME); + memcpy(mac_info->mac, mac_msg->mac_str, 32); mac_info->type = mac_type; mac_info->op_type = mac_msg->op_type; - msg_hdr->len = sizeof(struct IccpSyncdHDr)+sizeof(struct mclag_fdb_info); - + msg_hdr->len = sizeof(struct IccpSyncdHDr) + sizeof(struct mclag_fdb_info); + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d write mac msg vid : %d ; ifname %s ; mac %s fdb type %d ; op type %d ", - sys->sync_fd,mac_info->vid,mac_info->port_name,mac_info->mac, mac_info->type,mac_info->op_type); - + sys->sync_fd, mac_info->vid, mac_info->port_name, mac_info->mac, mac_info->type, mac_info->op_type); + /*send msg*/ - if(sys->sync_fd > 0 ) - write(sys->sync_fd,msg_buf, msg_hdr->len); + if (sys->sync_fd > 0 ) + write(sys->sync_fd, msg_buf, msg_hdr->len); return; } @@ -1032,7 +1041,7 @@ void add_mac_to_chip(struct MACMsg* mac_msg, uint8_t mac_type) { mac_msg->op_type = MAC_SYNC_ADD; iccp_send_fdb_entry_to_syncd( mac_msg, mac_type); - + return; } @@ -1040,7 +1049,7 @@ void del_mac_from_chip(struct MACMsg* mac_msg) { mac_msg->op_type = MAC_SYNC_DEL; iccp_send_fdb_entry_to_syncd( mac_msg, mac_msg->fdb_type); - + return; } @@ -1050,15 +1059,15 @@ uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t struct Msg *msg = NULL; new_age_flag = mac_msg->age_flag; - - if(set == 0)/*remove age flag*/ + + if (set == 0)/*remove age flag*/ { - if(new_age_flag & MAC_AGE_LOCAL) + if (new_age_flag & MAC_AGE_LOCAL) { new_age_flag &= ~MAC_AGE_LOCAL; - ICCPD_LOG_DEBUG(__FUNCTION__, "Remove local age flag: %d ifname %s, add %s vlan-id %d, age_flag %d", - new_age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove local age flag: %d ifname %s, add %s vlan-id %d, age_flag %d", + new_age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); /*send mac MAC_SYNC_ADD message to peer*/ if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) @@ -1067,21 +1076,21 @@ uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); } } } } else/*set age flag*/ { - if(!(new_age_flag & MAC_AGE_LOCAL)) + if (!(new_age_flag & MAC_AGE_LOCAL)) { new_age_flag |= MAC_AGE_LOCAL; - ICCPD_LOG_DEBUG(__FUNCTION__, "Add local age flag: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Add local age flag: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + /*send mac MAC_SYNC_DEL message to peer*/ if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { @@ -1089,53 +1098,53 @@ uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); } } } } - + return new_age_flag; } /*Deal with mac add,del,move when portchannel up or down*/ static void update_l2_mac_state(struct CSM *csm, - struct LocalInterface *lif, - int po_state) + struct LocalInterface *lif, + int po_state) { struct Msg* msg = NULL; struct MACMsg* mac_msg = NULL; - + if (!csm || !lif) return; - + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { - mac_msg = (struct MACMsg*) msg->buf; - + mac_msg = (struct MACMsg*)msg->buf; + /* find the MAC for this interface*/ if (strcmp(lif->name, mac_msg->origin_ifname) != 0) continue; /*portchannel down*/ - if(po_state == 0) + if (po_state == 0) { #if 1 mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); - - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down,flag %d del MAC: %s, MAC %s vlan-id %d", - mac_msg->age_flag, mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); - if(mac_msg->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down,flag %d del MAC: %s, MAC %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) { /*send mac del message to mclagsyncd.*/ - if(mac_msg->fdb_type != MAC_TYPE_STATIC) + if (mac_msg->fdb_type != MAC_TYPE_STATIC) del_mac_from_chip(mac_msg); - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, del MAC: %s, MAC %s vlan-id %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, del MAC: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + /*If local and peer both aged, del the mac*/ TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); free(msg->buf); @@ -1143,15 +1152,15 @@ static void update_l2_mac_state(struct CSM *csm, } else { - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, flag %d redirect MAC to peer-link: %s, MAC %s vlan-id %d", - mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); - - /*If local is aged but peer is not aged, redirect the mac to peer-link*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, flag %d redirect MAC to peer-link: %s, MAC %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + /*If local is aged but peer is not aged, redirect the mac to peer-link*/ memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); /*Send mac add message to mclagsyncd. fdb_type is not changed*/ /*Is need to delete the old item before add?(Old item probably is static)*/ - if(csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); } #endif @@ -1160,17 +1169,17 @@ static void update_l2_mac_state(struct CSM *csm, { if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf up, redirect MAC to portchannel: %s, MAC %s vlan-id %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf up, redirect MAC to portchannel: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + /*Remove MAC_AGE_LOCAL flag*/ - mac_msg->age_flag = set_mac_local_age_flag(csm,mac_msg, 0); - - /*Reverse interface from peer-link to the original portchannel*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 0); + + /*Reverse interface from peer-link to the original portchannel*/ memcpy(mac_msg->ifname, mac_msg->origin_ifname, MAX_L_PORT_NAME); /*Send dynamic or static mac add message to mclagsyncd*/ - add_mac_to_chip(mac_msg, mac_msg->fdb_type); + add_mac_to_chip(mac_msg, mac_msg->fdb_type); } } } @@ -1184,35 +1193,35 @@ void mlacp_portchannel_state_handler(struct CSM* csm, { if (!csm || !local_if) return; - + update_peerlink_isolate_from_lif(csm, local_if, po_state); update_l2_mac_state(csm, local_if, po_state); - - if(!local_if_is_l3_mode(local_if)) + + if (!local_if_is_l3_mode(local_if)) update_l2_po_state(csm, local_if, po_state); else update_l3_po_state(csm, local_if, po_state); - + update_po_if_info(csm, local_if, po_state); return; } -static void mlacp_conn_handler_fdb (struct CSM* csm) +static void mlacp_conn_handler_fdb(struct CSM* csm) { struct Msg* msg = NULL; struct MACMsg* mac_msg = NULL; - struct Msg *msg_send = NULL; + struct Msg *msg_send = NULL; if (!csm) - return; + return; - if(!TAILQ_EMPTY(&(MLACP(csm).mac_list))) + if (!TAILQ_EMPTY(&(MLACP(csm).mac_list))) { TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { - mac_msg = (struct MACMsg*) msg->buf; + mac_msg = (struct MACMsg*)msg->buf; /*Wait the ACK from peer?*/ /*mac_msg->age_flag &= ~MAC_AGE_PEER;*/ @@ -1223,8 +1232,8 @@ static void mlacp_conn_handler_fdb (struct CSM* csm) { mac_msg->age_flag &= ~MAC_AGE_PEER; TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); } } } @@ -1241,41 +1250,41 @@ void mlacp_peer_conn_handler(struct CSM* csm) struct LocalInterface *lif = NULL; static int first_time = 0; struct System* sys = NULL; - + if (!csm) return; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) return; - + set_peerlink_mlag_port_learn(csm->peer_link_if, 0); /*If peer connect again, don't flush FDB*/ - if(first_time == 0) + if (first_time == 0) { first_time = 1; /*If warm reboot, don't flush FDB*/ - if(sys->warmboot_start != WARM_REBOOT) + if (sys->warmboot_start != WARM_REBOOT) mlacp_clean_fdb(); } iccp_get_fdb_change_from_syncd(); - + mlacp_conn_handler_fdb(csm); - + #if 0 // When peer-link ready, suppose all MLAG link are alive LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next) { pif->po_active = 1; } -#endif +#endif LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) { - if(lif->type == IF_T_PORT_CHANNEL) + if (lif->type == IF_T_PORT_CHANNEL) { #if 0 - if(local_if_is_l3_mode(lif)) + if (local_if_is_l3_mode(lif)) { set_route_by_linux_route( csm, lif, 1); } @@ -1283,17 +1292,17 @@ void mlacp_peer_conn_handler(struct CSM* csm) { LIST_FOREACH(vlan, &(lif->vlan_list), port_next) { - if(!vlan->vlan_itf) + if (!vlan->vlan_itf) continue; - if(!local_if_is_l3_mode(vlan->vlan_itf)) + if (!local_if_is_l3_mode(vlan->vlan_itf)) continue; - + set_route_by_linux_route(csm, vlan->vlan_itf, 1); /* add static route by linux route tool*/ } } #endif - - mlacp_portchannel_state_handler(csm, lif,(lif->state==PORT_STATE_UP)?1:0); + + mlacp_portchannel_state_handler(csm, lif, (lif->state == PORT_STATE_UP) ? 1 : 0); } } @@ -1312,36 +1321,36 @@ void mlacp_peer_disconn_handler(struct CSM* csm) if (!csm) return; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) return; /*If warm reboot, don't change FDB and MAC address*/ - if(sys->warmboot_exit == WARM_REBOOT) + if (sys->warmboot_exit == WARM_REBOOT) return; /*If peer is warm reboot, don't change FDB and MAC address*/ - if(csm->peer_warm_reboot_time != 0) + if (csm->peer_warm_reboot_time != 0) { /*If peer disconnected, recover peer to normal reboot for next time*/ csm->peer_warm_reboot_time = 0; return; } - + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { - mac_msg = (struct MACMsg*) msg->buf; + mac_msg = (struct MACMsg*)msg->buf; mac_msg->age_flag |= MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, op_type %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); /* find the MAC that the port is peer-link or local and peer both aged, to be deleted*/ - if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0 && mac_msg->age_flag != (MAC_AGE_LOCAL|MAC_AGE_PEER)) + if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0 && mac_msg->age_flag != (MAC_AGE_LOCAL | MAC_AGE_PEER)) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "Peer disconnect, del MAC for peer-link: %s, MAC %s vlan-id %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer disconnect, del MAC for peer-link: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + /*Send mac del message to mclagsyncd*/ del_mac_from_chip(mac_msg); @@ -1353,14 +1362,14 @@ void mlacp_peer_disconn_handler(struct CSM* csm) memcpy(MLACP(csm).remote_system.system_id, null_mac, ETHER_ADDR_LEN); /*If peer is disconnected, recover the MAC address.*/ - if (csm->role_type == STP_ROLE_STANDBY) + if (csm->role_type == STP_ROLE_STANDBY) { LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) { recover_if_ipmac_on_standby(lif); } } - + return; } @@ -1375,15 +1384,15 @@ void mlacp_peerlink_up_handler(struct CSM* csm) /*If peer link up, set all the mac that point to the peer-link in ASIC*/ TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { - mac_msg = (struct MACMsg*) msg->buf; + mac_msg = (struct MACMsg*)msg->buf; /* Find the MAC that the port is peer-link to be added*/ if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "Peer link up, add MAC to ASIC for peer-link: %s, MAC %s vlan-id %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer link up, add MAC to ASIC for peer-link: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + /*Send mac add message to mclagsyncd, local age flag is already set*/ add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); } @@ -1402,22 +1411,22 @@ void mlacp_peerlink_down_handler(struct CSM* csm) /*If peer link down, remove all the mac that point to the peer-link*/ TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { - mac_msg = (struct MACMsg*) msg->buf; + mac_msg = (struct MACMsg*)msg->buf; /* Find the MAC that the port is peer-link to be deleted*/ if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) continue; mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); - - ICCPD_LOG_DEBUG(__FUNCTION__, "Peer link down, del MAC for peer-link: %s, MAC %s vlan-id %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer link down, del MAC for peer-link: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); /*Send mac del message to mclagsyncd*/ del_mac_from_chip(mac_msg); /*If peer is not age, keep the MAC in mac_list, but ASIC is deleted*/ - if(mac_msg->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) { /*If local and peer both aged, del the mac*/ TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); @@ -1437,8 +1446,9 @@ void mlacp_mlag_link_add_handler(struct CSM *csm, struct LocalInterface *lif) { if (!csm || !lif) return; - if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; - + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + set_peerlink_mlag_port_isolate(csm, lif, 1); return; @@ -1448,9 +1458,10 @@ void mlacp_mlag_link_del_handler(struct CSM *csm, struct LocalInterface *lif) { if (!csm || !lif) return; - - if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) return; - + + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + set_peerlink_mlag_port_isolate(csm, lif, 0); return; @@ -1463,24 +1474,25 @@ int iccp_connect_syncd() int fd = 0; struct sockaddr_in serv; static int count = 0; - struct epoll_event event; - + struct epoll_event event; + if ((sys = system_get_instance()) == NULL) goto conn_fail; - if(sys->sync_fd >= 0) + if (sys->sync_fd >= 0) return 0; /*Print the fail log message every 60s*/ - if(count >= 600) + if (count >= 600) { count = 0; } - + fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) + if (fd < 0) { - if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to create unix socket: %s", strerror(errno)); + if (count == 0) + ICCPD_LOG_WARN(__FUNCTION__, "Failed to create unix socket: %s", strerror(errno)); goto conn_fail; } @@ -1494,28 +1506,31 @@ int iccp_connect_syncd() serv.sin_addr.s_addr = htonl(0x7f000006); ret = connect(fd, (struct sockaddr *)&serv, sizeof(serv)); - if (ret < 0) { - if(count == 0) ICCPD_LOG_WARN(__FUNCTION__, "Failed to connect to mclag syncd: errno str %s", strerror(errno)); + if (ret < 0) + { + if (count == 0) + ICCPD_LOG_WARN(__FUNCTION__, "Failed to connect to mclag syncd: errno str %s", strerror(errno)); close(fd); goto conn_fail; } ICCPD_LOG_WARN(__FUNCTION__, "success to link syncd"); sys->sync_fd = fd; - + event.data.fd = fd; event.events = EPOLLIN; - ret = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, fd, &event); - + ret = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, fd, &event); + count = 0; return 0; - -conn_fail: - if(count == 0) ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclag syncd socket connect fail", - __FUNCTION__, __LINE__); + + conn_fail: + if (count == 0) + ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclag syncd socket connect fail", + __FUNCTION__, __LINE__); count++; - + return -1; } @@ -1525,8 +1540,8 @@ void syncd_info_close() if ((sys = system_get_instance()) == NULL) return; - - if(sys->sync_fd > 0) + + if (sys->sync_fd > 0) { close(sys->sync_fd); sys->sync_fd = -1; @@ -1535,13 +1550,13 @@ void syncd_info_close() return; } - int iccp_get_receive_fdb_sock_fd(struct System *sys) +int iccp_get_receive_fdb_sock_fd(struct System *sys) { return sys->sync_fd; } /*When received MAC add and del packets from mclagsyncd, update mac information*/ -void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uint8_t fdb_type, uint8_t op_type) +void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint8_t fdb_type, uint8_t op_type) { struct System *sys = NULL; struct CSM *csm = NULL; @@ -1552,16 +1567,16 @@ void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uin size_t msg_len = 0; uint8_t from_mclag_intf = 0;/*0: orphan port, 1: MCLAG port*/ struct CSM *first_csm = NULL; - + struct LocalInterface *lif_po = NULL, *mac_lif = NULL; - + if (!(sys = system_get_instance())) return; - + /* Find local itf*/ if (!(mac_lif = local_if_find_by_name(ifname))) return; - + /* create MAC msg*/ memset(buf, 0, MAX_BUFSIZE); msg_len = sizeof(struct MACMsg); @@ -1581,51 +1596,53 @@ void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uin fprintf(stderr, " MAC = %s\n", mac_str); fprintf(stderr, " ifname = %s\n", mac_lif->name); fprintf(stderr, " vlan id = %d\n", vid); - fprintf(stderr, " fdb type = %s\n", fdb_type==MAC_TYPE_STATIC?"static":"dynamic"); - fprintf(stderr, " op type = %s\n", op_type==MAC_SYNC_ADD?"add":"del"); + fprintf(stderr, " fdb type = %s\n", fdb_type == MAC_TYPE_STATIC ? "static" : "dynamic"); + fprintf(stderr, " op type = %s\n", op_type == MAC_SYNC_ADD ? "add" : "del"); fprintf(stderr, "==============================\n"); #endif - + /* Find MLACP itf, may be mclag enabled port-channel*/ LIST_FOREACH(csm, &(sys->csm_list), next) { - if(csm && !first_csm) + if (csm && !first_csm) { /*Record the first CSM, only one CSM in the system currently*/ first_csm = csm; } - + /*If MAC is from peer-link, break; peer-link is not in MLACP(csm).lif_list*/ - if (strcmp(ifname, csm->peer_itf_name) == 0) break; - + if (strcmp(ifname, csm->peer_itf_name) == 0) + break; + LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) { if (lif_po->type != IF_T_PORT_CHANNEL) continue; - if(strcmp(lif_po->name, ifname) == 0) + if (strcmp(lif_po->name, ifname) == 0) { from_mclag_intf = 1; break; } } - - if(from_mclag_intf == 1) + + if (from_mclag_intf == 1) break; } - if (!first_csm) return; + if (!first_csm) + return; /*If support multiple CSM, the MAC list of orphan port must be moved to sys->mac_list*/ csm = first_csm; - + /* find lif MAC+vid*/ TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { - mac_info = (struct MACMsg*) msg->buf; + mac_info = (struct MACMsg*)msg->buf; /*MAC and vid are equal*/ - if (strcmp(mac_info->mac_str, mac_str) == 0 && mac_info->vid== vid) + if (strcmp(mac_info->mac_str, mac_str) == 0 && mac_info->vid == vid) { mac_exist = 1; break; @@ -1633,25 +1650,25 @@ void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uin } /*handle mac add*/ - if(op_type == MAC_SYNC_ADD) + if (op_type == MAC_SYNC_ADD) { /*same MAC exist*/ - if(mac_exist) + if (mac_exist) { /*If the recv mac port is peer-link, that is add from iccpd, no need to handle*/ - if(strcmp(csm->peer_itf_name, mac_msg->ifname) == 0) + if (strcmp(csm->peer_itf_name, mac_msg->ifname) == 0) { return; } - + /*If the current mac port is peer-link, it will handle by port up event*/ /*if(strcmp(csm->peer_itf_name, mac_info->ifname) == 0) - { + { return; - }*/ - + }*/ + /* update MAC*/ - if(mac_info->fdb_type != mac_msg->fdb_type + if (mac_info->fdb_type != mac_msg->fdb_type || strcmp(mac_info->ifname, mac_msg->ifname) != 0 || strcmp(mac_info->origin_ifname, mac_msg->ifname) != 0) { @@ -1661,7 +1678,7 @@ void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uin /*Remove MAC_AGE_LOCAL flag*/ mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 0); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Update MAC for %s, ifname %s", mac_msg->mac_str, mac_msg->ifname); } else @@ -1669,93 +1686,93 @@ void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uin /*All info are the same, Remove MAC_AGE_LOCAL flag, then return*/ /*In theory, this will be happened that mac age and then learn*/ mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 0); - + return; } } else/*same MAC not exist*/ { - /*If the port the mac learn is change to down before the mac + /*If the port the mac learn is change to down before the mac sync to iccp, this mac must be deleted */ - if(mac_lif->state == PORT_STATE_DOWN) + if (mac_lif->state == PORT_STATE_DOWN) { del_mac_from_chip(mac_msg); - + return; } - + /*set MAC_AGE_PEER flag before send this item to peer*/ mac_msg->age_flag |= MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); mac_msg->op_type = MAC_SYNC_ADD; - + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { - struct Msg *msg_send = NULL; - if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, msg_len)==0) + struct Msg *msg_send = NULL; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, msg_len) == 0) { mac_msg->age_flag &= ~MAC_AGE_PEER; TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); } } /*enqueue mac to mac-list*/ - if (iccp_csm_init_msg(&msg, (char*)mac_msg, msg_len)==0) + if (iccp_csm_init_msg(&msg, (char*)mac_msg, msg_len) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-list enqueue: %s, add %s vlan-id %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-list enqueue: %s, add %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC %s, add %s vlan-id %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid); + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC %s, add %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); } } else/*handle mac del*/ { /*same MAC exist*/ - if(mac_exist) + if (mac_exist) { - if(strcmp(mac_info->ifname, csm->peer_itf_name) == 0) + if (strcmp(mac_info->ifname, csm->peer_itf_name) == 0) { /*Set MAC_AGE_LOCAL flag*/ mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 1); - - if(mac_info->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + + if (mac_info->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) { - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(peer-link), del %s vlan-id %d", - mac_info->ifname,mac_info->mac_str, mac_info->vid); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(peer-link), del %s vlan-id %d", + mac_info->ifname, mac_info->mac_str, mac_info->vid); /*If peer link is down, del the mac*/ TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); free(msg->buf); free(msg); } - else if(csm->peer_link_if && csm->peer_link_if->state != PORT_STATE_DOWN) + else if (csm->peer_link_if && csm->peer_link_if->state != PORT_STATE_DOWN) { /*peer-link learn mac is control by iccpd, ignore the chip del info*/ add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); - - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(peer-link is up), add back %s vlan-id %d", - mac_info->ifname,mac_info->mac_str, mac_info->vid); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(peer-link is up), add back %s vlan-id %d", + mac_info->ifname, mac_info->mac_str, mac_info->vid); } - + return; } /*Add MAC_AGE_LOCAL flag*/ mac_info->age_flag = set_mac_local_age_flag(csm, mac_info, 1); - if(mac_info->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + if (mac_info->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) { - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d", - mac_info->ifname,mac_info->mac_str, mac_info->vid); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d", + mac_info->ifname, mac_info->mac_str, mac_info->vid); + /*If local and peer both aged, del the mac*/ TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); free(msg->buf); @@ -1763,85 +1780,86 @@ void do_mac_update_from_syncd (char mac_str[32], uint16_t vid, char *ifname, uin } else { - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d, peer is not age, add back to chip", - mac_info->ifname,mac_info->mac_str, mac_info->vid); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d, peer is not age, add back to chip", + mac_info->ifname, mac_info->mac_str, mac_info->vid); - if(from_mclag_intf && lif_po && lif_po->state == PORT_STATE_DOWN) + if (from_mclag_intf && lif_po && lif_po->state == PORT_STATE_DOWN) { /*If local if is down, redirect the mac to peer-link*/ memcpy(&mac_info->ifname, csm->peer_itf_name, IFNAMSIZ); - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link", - mac_info->ifname,mac_info->mac_str, mac_info->vid); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link", + mac_info->ifname, mac_info->mac_str, mac_info->vid); } - + /*If local is aged but peer is not aged, Send mac add message to mclagsyncd*/ mac_info->fdb_type = MAC_TYPE_DYNAMIC; - + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); } } } - + return; } - int iccp_receive_fdb_handler_from_syncd(struct System *sys) +int iccp_receive_fdb_handler_from_syncd(struct System *sys) { - int n=0; + int n = 0; int count = 0; - int i =0; + int i = 0; char *msg_buf = g_csm_buf; - struct LocalInterface* lif = NULL; + struct LocalInterface* lif = NULL; struct IccpSyncdHDr * msg_hdr; struct mclag_fdb_info * mac_info; static time_t last_time = 0; - - if(sys == NULL) + + if (sys == NULL) return -1; memset(msg_buf, 0, CSM_BUFFER_SIZE); - + n = read(sys->sync_fd, msg_buf, CSM_BUFFER_SIZE); - if (n <=0) + if (n <= 0) { if (last_time == 0 || (time(NULL) - last_time) >= 60) - { - ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d read error ret = %d errno = %d ",sys->sync_fd, n, errno); + { + ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d read error ret = %d errno = %d ", sys->sync_fd, n, errno); last_time = time(NULL); } - + return -1; } msg_hdr = (struct IccpSyncdHDr *)msg_buf; - ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg version %d type %d len %d ",msg_hdr->ver , msg_hdr->type, msg_hdr->len ); + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg version %d type %d len %d ", msg_hdr->ver, msg_hdr->type, msg_hdr->len ); if (msg_hdr->ver != 1) { - ICCPD_LOG_DEBUG(__FUNCTION__, "msg version wrong!!!!! "); + ICCPD_LOG_DEBUG(__FUNCTION__, "msg version wrong!!!!! "); return -1; } if (msg_hdr->type == MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION) { - count =( msg_hdr->len- sizeof(struct IccpSyncdHDr ))/sizeof(struct mclag_fdb_info); - ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d ",count ); - for (i =0; ilen - sizeof(struct IccpSyncdHDr )) / sizeof(struct mclag_fdb_info); + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d ", count ); + + for (i = 0; i < count; i++) { - mac_info = (struct mclag_fdb_info *)&msg_buf[sizeof(struct IccpSyncdHDr )+ i * sizeof(struct mclag_fdb_info)]; - ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d vid %d mac %s port %s optype %d ",i, mac_info->vid, mac_info->mac, mac_info->port_name, mac_info->op_type); + mac_info = (struct mclag_fdb_info *)&msg_buf[sizeof(struct IccpSyncdHDr ) + i * sizeof(struct mclag_fdb_info)]; + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d vid %d mac %s port %s optype %d ", i, mac_info->vid, mac_info->mac, mac_info->port_name, mac_info->op_type); lif = local_if_find_by_name(mac_info->port_name); - + /*if (!lif ||lif->type != IF_T_PORT_CHANNEL)*/ if (!lif) continue; do_mac_update_from_syncd(mac_info->mac, mac_info->vid, mac_info->port_name, mac_info->type, mac_info->op_type); } - } - else + } + else { - ICCPD_LOG_DEBUG(__FUNCTION__, "recv unknown type msg " ); + ICCPD_LOG_DEBUG(__FUNCTION__, "recv unknown type msg " ); } - + return 0; } @@ -1850,20 +1868,25 @@ char * mclagd_ctl_cmd_str(int req_type) switch (req_type) { case INFO_TYPE_DUMP_STATE: - return "dump config"; + return "dump config"; + case INFO_TYPE_DUMP_ARP: - return "dump arp"; + return "dump arp"; + case INFO_TYPE_DUMP_MAC: - return "dump mac"; + return "dump mac"; + case INFO_TYPE_DUMP_LOCAL_PORTLIST: - return "dump local portlist"; - case INFO_TYPE_DUMP_PEER_PORTLIST: - return "dump peer portlist"; + return "dump local portlist"; + + case INFO_TYPE_DUMP_PEER_PORTLIST: + return "dump peer portlist"; + default: - break; + break; } - - return "error req type"; + + return "error req type"; } int mclagd_ctl_sock_create() @@ -1873,17 +1896,17 @@ int mclagd_ctl_sock_create() struct epoll_event event; int addr_len; int ret = 0; - + if ((sys = system_get_instance()) == NULL) - return -1;; + return -1; - if(sys->sync_ctrl_fd > 0) + if (sys->sync_ctrl_fd > 0) return sys->sync_ctrl_fd; sys->sync_ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(sys->sync_ctrl_fd < 0) + if (sys->sync_ctrl_fd < 0) { - ICCPD_LOG_WARN(__FUNCTION__, "Failed to create mclagd ctl sock\n"); + ICCPD_LOG_WARN(__FUNCTION__, "Failed to create mclagd ctl sock\n"); return sys->sync_ctrl_fd; } @@ -1894,14 +1917,14 @@ int mclagd_ctl_sock_create() snprintf(addr.sun_path, 107, "%s", sys->mclagdctl_file_path); addr_len = sizeof(addr.sun_family) + strlen(sys->mclagdctl_file_path); - if((ret = bind(sys->sync_ctrl_fd, (struct sockaddr*)&addr, addr_len)) < 0) + if ((ret = bind(sys->sync_ctrl_fd, (struct sockaddr*)&addr, addr_len)) < 0) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to bind mclagd ctl socket %s:%s\n", sys->mclagdctl_file_path, strerror(errno)); close(sys->sync_ctrl_fd); return -1; } - if(listen(sys->sync_ctrl_fd, 5) < 0) + if (listen(sys->sync_ctrl_fd, 5) < 0) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to listen unix mclagd ctl socket%s:%s\n", sys->mclagdctl_file_path, strerror(errno)); close(sys->sync_ctrl_fd); @@ -1910,10 +1933,10 @@ int mclagd_ctl_sock_create() event.data.fd = sys->sync_ctrl_fd; event.events = EPOLLIN; - epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, sys->sync_ctrl_fd, &event); - FD_SET(sys->sync_ctrl_fd, &(sys->readfd)); + epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, sys->sync_ctrl_fd, &event); + FD_SET(sys->sync_ctrl_fd, &(sys->readfd)); sys->readfd_count++; - + return sys->sync_ctrl_fd; } @@ -1922,9 +1945,9 @@ int mclagd_ctl_sock_accept(int fd) struct sockaddr_in client_addr; int client_fd = 0; unsigned int addr_len = 0; - + client_fd = accept(fd, (struct sockaddr*)&client_addr, &addr_len); - if(client_fd < 0) + if (client_fd < 0) { ICCPD_LOG_WARN(__FUNCTION__, "failed to accept a client from mclagdctl\n"); return -1; @@ -1933,64 +1956,66 @@ int mclagd_ctl_sock_accept(int fd) return client_fd; } -int mclagd_ctl_sock_read(int fd, char *r_buf ,int total_len) +int mclagd_ctl_sock_read(int fd, char *r_buf, int total_len) { - int read_len=0; - int ret=0; - struct timeval tv = {0}; + int read_len = 0; + int ret = 0; + struct timeval tv = { 0 }; fd_set read_fd; - - while(read_len < total_len) + + while (read_len < total_len) { FD_ZERO(&read_fd); FD_SET(fd, &read_fd); tv.tv_sec = 5; tv.tv_usec = 0; - + switch ((ret = select(fd + 1, &read_fd, NULL, NULL, &tv))) { case -1: - /* error*/ + /* error*/ case 0: /* timeout*/ - return -1; + return -1; + default: break; } - if(FD_ISSET(fd, &read_fd)) + + if (FD_ISSET(fd, &read_fd)) ret = read(fd, r_buf + read_len, total_len - read_len); - if(ret <= 0) + if (ret <= 0) { return -1; } read_len += ret; } - + return read_len; } -int mclagd_ctl_sock_write(int fd, char *w_buf ,int total_len) +int mclagd_ctl_sock_write(int fd, char *w_buf, int total_len) { - int write_len =0; - int ret=0; - - while(write_len < total_len) + int write_len = 0; + int ret = 0; + + while (write_len < total_len) { ret = write(fd, w_buf + write_len, total_len - write_len); - if(ret <= 0) + if (ret <= 0) { return 0; } write_len += ret; } - + return write_len; } void mclagd_ctl_handle_dump_state(int client_fd, int mclag_id) { char * Pbuf = NULL; - char buf[512] = {0}; + char buf[512] = { 0 }; int state_num = 0; int ret = 0; struct mclagd_reply_hdr *hd = NULL; @@ -2010,33 +2035,33 @@ void mclagd_ctl_handle_dump_state(int client_fd, int mclag_id) if (Pbuf) free(Pbuf); - + return; } hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); hd->exec_result = EXEC_TYPE_SUCCESS; hd->info_type = INFO_TYPE_DUMP_STATE; hd->data_len = state_num * sizeof(struct mclagd_state); - + len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); memcpy(Pbuf, &len_tmp, sizeof(int)); mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); - + if (Pbuf) - free(Pbuf); - + free(Pbuf); + return; } void mclagd_ctl_handle_dump_arp(int client_fd, int mclag_id) { char * Pbuf = NULL; - char buf[512] = {0}; + char buf[512] = { 0 }; int arp_num = 0; int ret = 0; struct mclagd_reply_hdr *hd = NULL; int len_tmp = 0; - + ret = iccp_arp_dump(&Pbuf, &arp_num, mclag_id); if (ret != EXEC_TYPE_SUCCESS) { @@ -2053,7 +2078,7 @@ void mclagd_ctl_handle_dump_arp(int client_fd, int mclag_id) return; } - + hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int)); hd->exec_result = EXEC_TYPE_SUCCESS; hd->info_type = INFO_TYPE_DUMP_ARP; @@ -2063,7 +2088,7 @@ void mclagd_ctl_handle_dump_arp(int client_fd, int mclag_id) mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); if (Pbuf) - free(Pbuf); + free(Pbuf); return; } @@ -2071,12 +2096,12 @@ void mclagd_ctl_handle_dump_arp(int client_fd, int mclag_id) void mclagd_ctl_handle_dump_mac(int client_fd, int mclag_id) { char * Pbuf = NULL; - char buf[512] = {0}; + char buf[512] = { 0 }; int mac_num = 0; int ret = 0; struct mclagd_reply_hdr *hd = NULL; int len_tmp = 0; - + ret = iccp_mac_dump(&Pbuf, &mac_num, mclag_id); if (ret != EXEC_TYPE_SUCCESS) { @@ -2101,7 +2126,7 @@ void mclagd_ctl_handle_dump_mac(int client_fd, int mclag_id) len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); memcpy(Pbuf, &len_tmp, sizeof(int)); mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); - + if (Pbuf) free(Pbuf); @@ -2111,12 +2136,12 @@ void mclagd_ctl_handle_dump_mac(int client_fd, int mclag_id) void mclagd_ctl_handle_dump_local_portlist(int client_fd, int mclag_id) { char * Pbuf = NULL; - char buf[512] = {0}; + char buf[512] = { 0 }; int lif_num = 0;; int ret = 0; struct mclagd_reply_hdr *hd = NULL; int len_tmp = 0; - + ret = iccp_local_if_dump(&Pbuf, &lif_num, mclag_id); if (ret != EXEC_TYPE_SUCCESS) { @@ -2141,7 +2166,7 @@ void mclagd_ctl_handle_dump_local_portlist(int client_fd, int mclag_id) len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); memcpy(Pbuf, &len_tmp, sizeof(int)); mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); - + if (Pbuf) free(Pbuf); @@ -2151,12 +2176,12 @@ void mclagd_ctl_handle_dump_local_portlist(int client_fd, int mclag_id) void mclagd_ctl_handle_dump_peer_portlist(int client_fd, int mclag_id) { char * Pbuf = NULL; - char buf[512] = {0}; + char buf[512] = { 0 }; int pif_num = 0; int ret = 0; struct mclagd_reply_hdr *hd = NULL; int len_tmp = 0; - + ret = iccp_peer_if_dump(&Pbuf, &pif_num, mclag_id); if (ret != EXEC_TYPE_SUCCESS) { @@ -2181,19 +2206,19 @@ void mclagd_ctl_handle_dump_peer_portlist(int client_fd, int mclag_id) len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); memcpy(Pbuf, &len_tmp, sizeof(int)); mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); - + if (Pbuf) - free(Pbuf); + free(Pbuf); return; } int mclagd_ctl_interactive_process(int client_fd) { - char buf[512] = {0}; - int ret = 0; + char buf[512] = { 0 }; + int ret = 0; - struct mclagdctl_req_hdr* req = NULL; + struct mclagdctl_req_hdr* req = NULL; if (client_fd < 0) return -1; @@ -2211,24 +2236,29 @@ int mclagd_ctl_interactive_process(int client_fd) { case INFO_TYPE_DUMP_STATE: mclagd_ctl_handle_dump_state(client_fd, req->mclag_id); - break; + break; + case INFO_TYPE_DUMP_ARP: - mclagd_ctl_handle_dump_arp(client_fd, req->mclag_id); - break; + mclagd_ctl_handle_dump_arp(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_MAC: - mclagd_ctl_handle_dump_mac(client_fd, req->mclag_id); - break; + mclagd_ctl_handle_dump_mac(client_fd, req->mclag_id); + break; + case INFO_TYPE_DUMP_LOCAL_PORTLIST: - mclagd_ctl_handle_dump_local_portlist(client_fd, req->mclag_id); - break; - case INFO_TYPE_DUMP_PEER_PORTLIST: - mclagd_ctl_handle_dump_peer_portlist(client_fd, req->mclag_id); - break; + mclagd_ctl_handle_dump_local_portlist(client_fd, req->mclag_id); + break; + + case INFO_TYPE_DUMP_PEER_PORTLIST: + mclagd_ctl_handle_dump_peer_portlist(client_fd, req->mclag_id); + break; + default: - return -1; + return -1; } - - return 0; + + return 0; } diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c index 48b97ab3af64..89b5be6caa17 100644 --- a/src/iccpd/src/mlacp_sync_prepare.c +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -1,27 +1,27 @@ /* -* MLACP Sync Infomation Preparation -* mlacp_sync_prepare.c + * MLACP Sync Infomation Preparation + * mlacp_sync_prepare.c -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -* -*/ + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + * + */ #include #include @@ -52,45 +52,45 @@ int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_bu ICCHdr* icc_hdr = NULL; mLACPSyncReqTLV* tlv = NULL; size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncReqTLV); - - if(csm == NULL) + + if (csm == NULL) return -1; - - if(buf == NULL) + + if (buf == NULL) return -1; - - if(msg_len > max_buf_size) + + if (msg_len > max_buf_size) return -1; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return -1; - + /* Prepare for sync request */ memset(buf, 0, max_buf_size); - - icc_hdr = (ICCHdr*) buf; - tlv = (mLACPSyncReqTLV*) &buf[sizeof(ICCHdr)]; - + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPSyncReqTLV*)&buf[sizeof(ICCHdr)]; + /* ICC header */ mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* mLACP Synchronization Request TLV */ tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; tlv->icc_parameter.type = htons(TLV_T_MLACP_SYNC_REQUEST); tlv->icc_parameter.len = htons(sizeof(mLACPSyncReqTLV) - sizeof(ICCParameter)); - + tlv->req_num = 0; MLACP(csm).sync_req_num = 0; - + tlv->c_bit = 1; tlv->s_bit = 1; - tlv->req_type = 0x3FFF; - *(uint16_t *)((uint8_t *)tlv+sizeof(ICCParameter)+sizeof(uint16_t)) = htons(*(uint16_t *)((uint8_t *)tlv+sizeof(ICCParameter)+sizeof(uint16_t))); - + tlv->req_type = 0x3FFF; + *(uint16_t *)((uint8_t *)tlv + sizeof(ICCParameter) + sizeof(uint16_t)) = htons(*(uint16_t *)((uint8_t *)tlv + sizeof(ICCParameter) + sizeof(uint16_t))); + tlv->port_num_agg_id = 0; tlv->actor_key = 0; - + return msg_len; } @@ -101,43 +101,43 @@ int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_bu int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end) { struct System* sys = NULL; - ICCHdr* icc_hdr = (ICCHdr*) buf; - mLACPSyncDataTLV* tlv = (mLACPSyncDataTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + mLACPSyncDataTLV* tlv = (mLACPSyncDataTLV*)&buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncDataTLV); - - if(csm == NULL) + + if (csm == NULL) return -1; - - if(buf == NULL) + + if (buf == NULL) return -1; - - if(msg_len > max_buf_size) + + if (msg_len > max_buf_size) return -1; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return -1; - + /* Prepare for sync request */ memset(buf, 0, max_buf_size); - - icc_hdr = (ICCHdr*) buf; - tlv = (mLACPSyncDataTLV*) &buf[sizeof(ICCHdr)]; - + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPSyncDataTLV*)&buf[sizeof(ICCHdr)]; + /* ICC header */ mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* mLACP Synchronization Data TLV */ tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; - tlv->icc_parameter.type = htons(TLV_T_MLACP_SYNC_DATA); + tlv->icc_parameter.type = htons(TLV_T_MLACP_SYNC_DATA); tlv->icc_parameter.len = htons(sizeof(mLACPSyncDataTLV) - sizeof(ICCParameter)); - + tlv->req_num = htons(MLACP(csm).sync_req_num); - if(end == 0) + if (end == 0) tlv->flags = 0x00; else tlv->flags = htons(0x01); - + return msg_len; } @@ -145,40 +145,40 @@ int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_s * Prprare Sync System-Config TLV * * ***************************************/ -int mlacp_prepare_for_sys_config(struct CSM* csm,char* buf, size_t max_buf_size) +int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size) { struct System* sys = NULL; - ICCHdr* icc_hdr = (ICCHdr*) buf; - mLACPSysConfigTLV* tlv = (mLACPSysConfigTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + mLACPSysConfigTLV* tlv = (mLACPSysConfigTLV*)&buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSysConfigTLV); - - if(csm == NULL) + + if (csm == NULL) return -1; - - if(buf == NULL) + + if (buf == NULL) return -1; - - if(msg_len > max_buf_size) + + if (msg_len > max_buf_size) return -1; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return -1; - + /* Prepare for sync request */ memset(buf, 0, max_buf_size); - - icc_hdr = (ICCHdr*) buf; - tlv = (mLACPSysConfigTLV*) &buf[sizeof(ICCHdr)]; - + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPSysConfigTLV*)&buf[sizeof(ICCHdr)]; + /* ICC header */ mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* System Config TLV */ tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; tlv->icc_parameter.type = htons(TLV_T_MLACP_SYSTEM_CONFIG); tlv->icc_parameter.len = htons(sizeof(mLACPSysConfigTLV) - sizeof(ICCParameter)); - + memcpy(tlv->sys_id, MLACP(csm).system_id, ETHER_ADDR_LEN); tlv->sys_priority = htons(MLACP(csm).system_priority); tlv->node_id = MLACP(csm).node_id; @@ -186,52 +186,52 @@ int mlacp_prepare_for_sys_config(struct CSM* csm,char* buf, size_t max_buf_size) } /*Prprare Sync AggPort-State TLV */ -int mlacp_prepare_for_Aggport_state(struct CSM* csm,char* buf, size_t max_buf_size, struct LocalInterface* local_if) +int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* local_if) { struct System* sys = NULL; - ICCHdr* icc_hdr = (ICCHdr*) buf; - mLACPAggPortStateTLV* tlv = (mLACPAggPortStateTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + mLACPAggPortStateTLV* tlv = (mLACPAggPortStateTLV*)&buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggPortStateTLV); - - if(csm == NULL) + + if (csm == NULL) return -1; - - if(buf == NULL) + + if (buf == NULL) return -1; - - if(local_if == NULL) + + if (local_if == NULL) return -1; - - if(local_if->type != IF_T_PORT_CHANNEL) + + if (local_if->type != IF_T_PORT_CHANNEL) return -1; - - if(msg_len > max_buf_size) + + if (msg_len > max_buf_size) return -1; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return -1; - + /* Prepare for sync request */ memset(buf, 0, max_buf_size); - - icc_hdr = (ICCHdr*) buf; - tlv = (mLACPAggPortStateTLV*) &buf[sizeof(ICCHdr)]; - + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPAggPortStateTLV*)&buf[sizeof(ICCHdr)]; + /* ICC header */ mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* Port State TLV */ tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; tlv->icc_parameter.type = htons(TLV_T_MLACP_AGGREGATOR_STATE); tlv->icc_parameter.len = htons(sizeof(mLACPAggPortStateTLV) - sizeof(ICCParameter)); - + tlv->partner_sys_priority = 0; tlv->partner_key = 0; tlv->agg_id = htons(local_if->po_id); tlv->actor_key = 0; tlv->agg_state = local_if->state; - + return msg_len; } @@ -240,145 +240,145 @@ int mlacp_prepare_for_Aggport_state(struct CSM* csm,char* buf, size_t max_buf_si * * ***************************************/ int mlacp_prepare_for_Aggport_config(struct CSM* csm, - char* buf, size_t max_buf_size, - struct LocalInterface* lif, int purge_flag) + char* buf, size_t max_buf_size, + struct LocalInterface* lif, int purge_flag) { - ICCHdr* icc_hdr = (ICCHdr*) buf; - mLACPAggConfigTLV* tlv = (mLACPAggConfigTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + mLACPAggConfigTLV* tlv = (mLACPAggConfigTLV*)&buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggConfigTLV); - - if(csm == NULL) + + if (csm == NULL) return -1; - - if(buf == NULL) + + if (buf == NULL) return -1; - - if(msg_len > max_buf_size) + + if (msg_len > max_buf_size) return -1; - + /* Prepare for sync request */ memset(buf, 0, max_buf_size); - - icc_hdr = (ICCHdr*) buf; - tlv = (mLACPAggConfigTLV*) &buf[sizeof(ICCHdr)]; - + + icc_hdr = (ICCHdr*)buf; + tlv = (mLACPAggConfigTLV*)&buf[sizeof(ICCHdr)]; + /* ICC header */ mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* Port Config TLV */ tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; tlv->icc_parameter.type = htons(TLV_T_MLACP_AGGREGATOR_CONFIG); - - tlv->icc_parameter.len = htons(sizeof(mLACPAggConfigTLV) - sizeof(ICCParameter)); + + tlv->icc_parameter.len = htons(sizeof(mLACPAggConfigTLV) - sizeof(ICCParameter)); tlv->agg_id = htons(lif->po_id); - if(purge_flag == 1) - tlv->flags = 0x02; /*purge*/ + if (purge_flag == 1) + tlv->flags = 0x02; /*purge*/ else - tlv->flags = 0x1; + tlv->flags = 0x1; tlv->agg_name_len = strlen(lif->name); memcpy(tlv->agg_name, lif->name, MAX_L_PORT_NAME); memcpy(tlv->mac_addr, lif->mac_addr, ETHER_ADDR_LEN); - + return msg_len; } /***************************************** * Preprare Sync MAC-Info TLV -* +* * ***************************************/ -int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg) +int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg) { struct mLACPMACInfoTLV* tlv = NULL; size_t msg_len = 0; size_t tlv_len = 0; ICCHdr* icc_hdr = NULL; - + if (!csm) return -1; if (!buf) return -1; - + tlv_len = sizeof(struct mLACPMACInfoTLV); - + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) return -1; - + /* ICC header */ memset(buf, 0, max_buf_size); - icc_hdr = (ICCHdr*) buf; + icc_hdr = (ICCHdr*)buf; mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* Prepare for ARP information TLV */ - tlv = (struct mLACPMACInfoTLV*) malloc(tlv_len); + tlv = (struct mLACPMACInfoTLV*)malloc(tlv_len); memset(tlv, 0, tlv_len); tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; - tlv->icc_parameter.type = htons(TLV_T_MLACP_MAC_INFO); + tlv->icc_parameter.type = htons(TLV_T_MLACP_MAC_INFO); tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)); tlv->type = mac_msg->op_type; sprintf(tlv->mac_str, "%s", mac_msg->mac_str); sprintf(tlv->ifname, "%s", mac_msg->origin_ifname); tlv->vid = htons(mac_msg->vid); - + /* Fill MAC Information TLV */ memcpy(&buf[sizeof(ICCHdr)], tlv, tlv_len); free(tlv); - + #if 1 ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg type = TLV_T_MLACP_MAC_INFO"); ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s mac = %s, vid = %d, type = %d", mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); #endif - + return msg_len; } /***************************************** * Preprare Sync ARP-Info TLV -* +* * ***************************************/ -int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg) +int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg) { struct mLACPARPInfoTLV* tlv = NULL; size_t msg_len = 0; size_t tlv_len = 0; ICCHdr* icc_hdr = NULL; - + if (!csm) return -1; if (!buf) return -1; - + tlv_len = sizeof(struct mLACPARPInfoTLV); - + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) return -1; - + /* ICC header */ memset(buf, 0, max_buf_size); - icc_hdr = (ICCHdr*) buf; + icc_hdr = (ICCHdr*)buf; mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* Prepare for ARP information TLV */ - tlv = (struct mLACPARPInfoTLV*) malloc(tlv_len); + tlv = (struct mLACPARPInfoTLV*)malloc(tlv_len); memset(tlv, 0, tlv_len); tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; - tlv->icc_parameter.type = htons(TLV_T_MLACP_ARP_INFO); + tlv->icc_parameter.type = htons(TLV_T_MLACP_ARP_INFO); tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)); tlv->type = arp_msg->op_type; sprintf(tlv->ifname, "%s", arp_msg->ifname); tlv->ipv4_addr = htonl(arp_msg->ipv4_addr); memcpy(tlv->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); - + /* Fill ARP Information TLV */ memcpy(&buf[sizeof(ICCHdr)], tlv, tlv_len); free(tlv); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s msg ifname %s mac =%02x:%02x:%02x:%02x:%02x:%02x ", tlv->ifname, arp_msg->ifname, tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], - tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); - ICCPD_LOG_DEBUG(__FUNCTION__, " IP Addr = %s ",show_ip_str( tlv->ipv4_addr)); - + tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + ICCPD_LOG_DEBUG(__FUNCTION__, " IP Addr = %s ", show_ip_str( tlv->ipv4_addr)); + return msg_len; } @@ -394,11 +394,11 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, ICCHdr* icc_hdr = NULL; struct mLACPPortChannelInfoTLV* tlv = NULL; size_t msg_len; - size_t tlv_len; + size_t tlv_len; size_t name_len = MAX_L_PORT_NAME; struct VLAN_ID* vlan_id = NULL; int num_of_vlan_id = 0; - + if (csm == NULL ) return -1; if (buf == NULL ) @@ -412,52 +412,53 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, /* Calculate VLAN ID Length */ LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next) - if (vlan_id != NULL) num_of_vlan_id++; - + if (vlan_id != NULL) + num_of_vlan_id++; + tlv_len = sizeof(struct mLACPPortChannelInfoTLV) + sizeof(struct VLAN_ID) * num_of_vlan_id; - + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) return -1; - + /* Prepare for port channel info */ memset(buf, 0, max_buf_size); - - icc_hdr = (ICCHdr*) buf; - tlv = (struct mLACPPortChannelInfoTLV*) &buf[sizeof(ICCHdr)]; - + + icc_hdr = (ICCHdr*)buf; + tlv = (struct mLACPPortChannelInfoTLV*)&buf[sizeof(ICCHdr)]; + /* ICC header */ mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* Port Channel Info TLV */ tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; - tlv->icc_parameter.type = htons(TLV_T_MLACP_PORT_CHANNEL_INFO); - tlv->icc_parameter.len = htons(sizeof(struct mLACPPortChannelInfoTLV) - sizeof(ICCParameter) + sizeof(struct VLAN_ID) *num_of_vlan_id) ; + tlv->icc_parameter.type = htons(TLV_T_MLACP_PORT_CHANNEL_INFO); + tlv->icc_parameter.len = htons(sizeof(struct mLACPPortChannelInfoTLV) - sizeof(ICCParameter) + sizeof(struct VLAN_ID) * num_of_vlan_id); tlv->agg_id = htons(port_channel->po_id); tlv->ipv4_addr = htonl(port_channel->ipv4_addr); tlv->l3_mode = port_channel->l3_mode; tlv->po_id = htons(port_channel->po_id); - if(strlen(port_channel->name) < name_len) + if (strlen(port_channel->name) < name_len) name_len = strlen(port_channel->name); memcpy(tlv->if_name, port_channel->name, name_len); tlv->if_name_len = name_len; tlv->num_of_vlan_id = htons(num_of_vlan_id); - + num_of_vlan_id = 0; LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next) { - if (vlan_id != NULL ) + if (vlan_id != NULL ) { tlv->vlanData[num_of_vlan_id].vlan_id = htons(vlan_id->vid); - + num_of_vlan_id++; ICCPD_LOG_DEBUG(__FUNCTION__, " port channel %d: addr = %s vlan id %d num %d ", port_channel->po_id, show_ip_str( tlv->ipv4_addr), vlan_id->vid, num_of_vlan_id ); } - } + } ICCPD_LOG_DEBUG(__FUNCTION__, " port channel %d: addr = %s l3 mode %d", port_channel->po_id, show_ip_str( tlv->ipv4_addr), tlv->l3_mode); - + return msg_len; } @@ -466,15 +467,15 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, * * ***************************************/ int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, - size_t max_buf_size, - struct LocalInterface* peerlink_port) + size_t max_buf_size, + struct LocalInterface* peerlink_port) { struct System* sys = NULL; ICCHdr* icc_hdr = NULL; struct mLACPPeerLinkInfoTLV* tlv = NULL; size_t msg_len; - size_t tlv_len; - + size_t tlv_len; + if (csm == NULL ) return -1; if (buf == NULL ) @@ -483,33 +484,33 @@ int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, return -1; if ((sys = system_get_instance()) == NULL ) return -1; - + /* Prepare for port channel info */ memset(buf, 0, max_buf_size); - - tlv_len = sizeof(struct mLACPPeerLinkInfoTLV); - + + tlv_len = sizeof(struct mLACPPeerLinkInfoTLV); + if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) return -1; - - icc_hdr = (ICCHdr*) buf; - tlv = (struct mLACPPeerLinkInfoTLV*) &buf[sizeof(ICCHdr)]; - + + icc_hdr = (ICCHdr*)buf; + tlv = (struct mLACPPeerLinkInfoTLV*)&buf[sizeof(ICCHdr)]; + /* ICC header */ mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* Port Channel Info TLV */ tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; tlv->icc_parameter.type = htons(TLV_T_MLACP_PEERLINK_INFO); - - tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)) ; + + tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)); memcpy(tlv->if_name, peerlink_port->name, MAX_L_PORT_NAME); tlv->port_type = peerlink_port->type; - + ICCPD_LOG_DEBUG(__FUNCTION__, " peerlink port info portname %s type = %d", tlv->if_name, tlv->port_type); - + return msg_len; } @@ -518,40 +519,40 @@ int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, * Prprare Send Heartbeat * * ***************************************/ -int mlacp_prepare_for_heartbeat(struct CSM* csm,char* buf, size_t max_buf_size) +int mlacp_prepare_for_heartbeat(struct CSM* csm, char* buf, size_t max_buf_size) { struct System* sys = NULL; - ICCHdr* icc_hdr = (ICCHdr*) buf; - struct mLACPHeartbeatTLV* tlv = (struct mLACPHeartbeatTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + struct mLACPHeartbeatTLV* tlv = (struct mLACPHeartbeatTLV*)&buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPHeartbeatTLV); - - if(csm == NULL) + + if (csm == NULL) return -1; - - if(buf == NULL) + + if (buf == NULL) return -1; - - if(msg_len > max_buf_size) + + if (msg_len > max_buf_size) return -1; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return -1; - + /* Prepare for sync request */ memset(buf, 0, max_buf_size); - - icc_hdr = (ICCHdr*) buf; - tlv = (struct mLACPHeartbeatTLV*) &buf[sizeof(ICCHdr)]; - + + icc_hdr = (ICCHdr*)buf; + tlv = (struct mLACPHeartbeatTLV*)&buf[sizeof(ICCHdr)]; + /* ICC header */ mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* System Config TLV */ tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; tlv->icc_parameter.type = htons(TLV_T_MLACP_HEARTBEAT); - - tlv->icc_parameter.len = htons(sizeof(struct mLACPHeartbeatTLV) - sizeof(ICCParameter)); + + tlv->icc_parameter.len = htons(sizeof(struct mLACPHeartbeatTLV) - sizeof(ICCParameter)); tlv->heartbeat = 0xFF; return msg_len; } @@ -560,40 +561,40 @@ int mlacp_prepare_for_heartbeat(struct CSM* csm,char* buf, size_t max_buf_size) * Prepare Send warm-reboot flag * * ***************************************/ -int mlacp_prepare_for_warm_reboot(struct CSM* csm,char* buf, size_t max_buf_size) +int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_size) { struct System* sys = NULL; - ICCHdr* icc_hdr = (ICCHdr*) buf; - struct mLACPWarmbootTLV* tlv = (struct mLACPWarmbootTLV*) &buf[sizeof(ICCHdr)]; + ICCHdr* icc_hdr = (ICCHdr*)buf; + struct mLACPWarmbootTLV* tlv = (struct mLACPWarmbootTLV*)&buf[sizeof(ICCHdr)]; size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPWarmbootTLV); - - if(csm == NULL) + + if (csm == NULL) return -1; - - if(buf == NULL) + + if (buf == NULL) return -1; - - if(msg_len > max_buf_size) + + if (msg_len > max_buf_size) return -1; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return -1; - + /* Prepare for sync request */ memset(buf, 0, max_buf_size); - - icc_hdr = (ICCHdr*) buf; - tlv = (struct mLACPWarmbootTLV*) &buf[sizeof(ICCHdr)]; - + + icc_hdr = (ICCHdr*)buf; + tlv = (struct mLACPWarmbootTLV*)&buf[sizeof(ICCHdr)]; + /* ICC header */ mlacp_fill_icc_header(csm, icc_hdr, msg_len); - + /* System Config TLV */ tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; tlv->icc_parameter.type = htons(TLV_T_MLACP_WARMBOOT_FLAG); - - tlv->icc_parameter.len = htons(sizeof(struct mLACPWarmbootTLV) - sizeof(ICCParameter)); + + tlv->icc_parameter.len = htons(sizeof(struct mLACPWarmbootTLV) - sizeof(ICCParameter)); tlv->warmboot = 0x1; return msg_len; } @@ -604,18 +605,18 @@ int mlacp_prepare_for_warm_reboot(struct CSM* csm,char* buf, size_t max_buf_size * ***************************************/ static int mlacp_fill_icc_header(struct CSM* csm, ICCHdr* icc_hdr, size_t msg_len) { - if(csm == NULL || icc_hdr == NULL) + if (csm == NULL || icc_hdr == NULL) return -1; - + /* ICC header */ icc_hdr->ldp_hdr.u_bit = 0x0; icc_hdr->ldp_hdr.msg_type = htons(MSG_T_RG_APP_DATA); - + icc_hdr->ldp_hdr.msg_len = htons(msg_len - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); icc_hdr->ldp_hdr.msg_id = htonl(ICCP_MSG_ID); ICCP_MSG_ID++; iccp_csm_fill_icc_rg_id_tlv(csm, icc_hdr); - + return 0; } diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c index af68244edd56..143dc45bf121 100644 --- a/src/iccpd/src/mlacp_sync_update.c +++ b/src/iccpd/src/mlacp_sync_update.c @@ -1,25 +1,25 @@ /******************************************************************************** -* mlacp_sync_update.c -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -* -*******************************************************************************/ + * mlacp_sync_update.c + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + * + *******************************************************************************/ #include #include @@ -39,23 +39,30 @@ * ***************************************/ extern void update_if_ipmac_on_standby(struct LocalInterface* lif_po); int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV*sysconf) -{ +{ + struct LocalInterface* lif = NULL; + /*NOTE - a little tricky, we change the NodeID local side if collision happened first time*/ - if(sysconf->node_id == MLACP(csm).node_id) + a little tricky, we change the NodeID local side if collision happened first time*/ + if (sysconf->node_id == MLACP(csm).node_id) MLACP(csm).node_id++; - + memcpy(MLACP(csm).remote_system.system_id, sysconf->sys_id, ETHER_ADDR_LEN); MLACP(csm).remote_system.system_priority = ntohs(sysconf->sys_priority); MLACP(csm).remote_system.node_id = sysconf->node_id; ICCPD_LOG_DEBUG(__FUNCTION__, " SystemID [%02X:%02X:%02X:%02X:%02X:%02X]. SystemPriority [%d], Remote NodeID [%d], NodeID [%d]", - MLACP(csm).remote_system.system_id[0],MLACP(csm).remote_system.system_id[1],MLACP(csm).remote_system.system_id[2], - MLACP(csm).remote_system.system_id[3],MLACP(csm).remote_system.system_id[4],MLACP(csm).remote_system.system_id[5], + MLACP(csm).remote_system.system_id[0], MLACP(csm).remote_system.system_id[1], MLACP(csm).remote_system.system_id[2], + MLACP(csm).remote_system.system_id[3], MLACP(csm).remote_system.system_id[4], MLACP(csm).remote_system.system_id[5], MLACP(csm).remote_system.system_priority, MLACP(csm).remote_system.node_id, MLACP(csm).node_id); - + + LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) + { + update_if_ipmac_on_standby(lif); + } + return 0; } @@ -66,19 +73,18 @@ int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV*sysconf) int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf) { struct PeerInterface* pif = NULL; - struct LocalInterface* lif = NULL; uint8_t po_active; uint8_t new_create = 0; ICCPD_LOG_DEBUG(__FUNCTION__, " Port name %s, po id %d flag %d MAC[%02x:%02x:%02x:%02x:%02x:%02x] ", - portconf->agg_name,ntohs(portconf->agg_id), portconf->flags,portconf->mac_addr[0], portconf->mac_addr[1], portconf->mac_addr[2], - portconf->mac_addr[3], portconf->mac_addr[4], portconf->mac_addr[5] ); - + portconf->agg_name, ntohs(portconf->agg_id), portconf->flags, portconf->mac_addr[0], portconf->mac_addr[1], portconf->mac_addr[2], + portconf->mac_addr[3], portconf->mac_addr[4], portconf->mac_addr[5] ); + /* Looking for the peer port instance, is any peer if exist?*/ pif = peer_if_find_by_name(csm, portconf->agg_name); - + /* Process purge*/ - if (portconf->flags & 0x02) + if (portconf->flags & 0x02) { /*Purge*/ if (pif != NULL ) @@ -87,33 +93,28 @@ int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf) MLACP(csm).need_to_sync = 1; /*ICCPD_LOG_INFO("mlacp_fsm", " Peer port %s is removed from port-channel member.",portconf->port_name);*/ - + return 0; } - if(pif == NULL && portconf->flags & 0x01) + if (pif == NULL && portconf->flags & 0x01) { pif = peer_if_create(csm, ntohs(portconf->agg_id), IF_T_PORT_CHANNEL); - if(pif == NULL) return -1; + if (pif == NULL) + return -1; - new_create= 1; + new_create = 1; } - + pif->po_id = ntohs(portconf->agg_id); memcpy(pif->name, portconf->agg_name, portconf->agg_name_len); memcpy(pif->mac_addr, portconf->mac_addr, ETHER_ADDR_LEN); - LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) - { - if (strcmp(lif->name,pif->name) == 0) - update_if_ipmac_on_standby(lif); - } - po_active = (pif->state == PORT_STATE_UP); update_stp_peer_link(csm, pif, po_active, new_create); - update_peerlink_isolate_from_pif(csm, pif, po_active, new_create); + update_peerlink_isolate_from_pif(csm, pif, po_active, new_create); pif->po_active = po_active; - + return 0; } @@ -125,18 +126,18 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) { struct PeerInterface* peer_if = NULL; uint8_t po_active; - - if(csm == NULL || tlv == NULL) + + if (csm == NULL || tlv == NULL) return -255; - ICCPD_LOG_DEBUG(__FUNCTION__, " po id %d state %d ",ntohs(tlv->agg_id), tlv->agg_state); + ICCPD_LOG_DEBUG(__FUNCTION__, " po id %d state %d ", ntohs(tlv->agg_id), tlv->agg_state); po_active = (tlv->agg_state == PORT_STATE_UP); - + LIST_FOREACH(peer_if, &(MLACP(csm).pif_list), mlacp_next) { if (peer_if->type != IF_T_PORT_CHANNEL) continue; - + if (peer_if->po_id != ntohs(tlv->agg_id)) continue; @@ -146,19 +147,19 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) update_peerlink_isolate_from_pif(csm, peer_if, po_active, 0); peer_if->po_active = po_active; - ICCPD_LOG_DEBUG(__FUNCTION__, "Update Msg for %s state %s",peer_if->name, tlv->agg_state? "down" : "up"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update Msg for %s state %s", peer_if->name, tlv->agg_state ? "down" : "up"); break; } - + return 0; } - /***************************************** - * Recv from peer, MAC-Info Update - * ***************************************/ - int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* tlv) - { +/***************************************** +* Recv from peer, MAC-Info Update +* ***************************************/ +int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* tlv) +{ struct Msg* msg = NULL; struct MACMsg *mac_msg = NULL, mac_data; struct LocalInterface* local_if = NULL; @@ -169,8 +170,8 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) #if 1 ICCPD_LOG_INFO(__FUNCTION__, - "Received MAC Info, itf=[%s] vid[%d] MAC[%s] type %d ", - tlv->ifname, ntohs(tlv->vid), tlv->mac_str, tlv->type); + "Received MAC Info, itf=[%s] vid[%d] MAC[%s] type %d ", + tlv->ifname, ntohs(tlv->vid), tlv->mac_str, tlv->type); #endif /*Find the interface in MCLAG interface list*/ @@ -183,7 +184,7 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) } } - if(!local_if) + if (!local_if) { if (!(local_if = local_if_find_by_name(tlv->ifname))) { @@ -195,22 +196,22 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) /* update MAC list*/ TAILQ_FOREACH(msg, &(MLACP(csm).mac_list), tail) { - mac_msg = (struct MACMsg*) msg->buf; - + mac_msg = (struct MACMsg*)msg->buf; + /*Same MAC is exist in local switch*/ - if (strcmp(mac_msg->mac_str, tlv->mac_str) == 0 && mac_msg->vid == ntohs(tlv->vid)) + if (strcmp(mac_msg->mac_str, tlv->mac_str) == 0 && mac_msg->vid == ntohs(tlv->vid)) { - if(tlv->type == MAC_SYNC_ADD) + if (tlv->type == MAC_SYNC_ADD) { mac_msg->age_flag &= ~MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", - mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + /*mac_msg->fdb_type = tlv->fdb_type;*/ /*The port ifname is different to the local item*/ - if(strcmp(mac_msg->ifname, tlv->ifname) != 0 || strcmp(mac_msg->origin_ifname, tlv->ifname) != 0) + if (strcmp(mac_msg->ifname, tlv->ifname) != 0 || strcmp(mac_msg->origin_ifname, tlv->ifname) != 0) { - if(mac_msg->fdb_type != MAC_TYPE_STATIC) + if (mac_msg->fdb_type != MAC_TYPE_STATIC) { /*Update local item*/ memcpy(&mac_msg->ifname, tlv->ifname, MAX_L_PORT_NAME); @@ -218,7 +219,7 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) } /*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/ - if(from_mclag_intf == 0 || (local_if->state == PORT_STATE_DOWN && strcmp(mac_msg->ifname, csm->peer_itf_name) != 0)) + if (from_mclag_intf == 0 || (local_if->state == PORT_STATE_DOWN && strcmp(mac_msg->ifname, csm->peer_itf_name) != 0)) { /*Redirect the mac to peer-link*/ memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); @@ -233,21 +234,21 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) #if 0 mac_msg->op_type = MAC_SYNC_ACK; - if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { /*Reply mac ack message to peer, peer will clean MAC_AGE_PEER flag*/ TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, MAC-msg-list enqueue: %s, add %s vlan-id %d, op_type %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, MAC-msg-list enqueue: %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); } #endif } - else if(tlv->type == MAC_SYNC_ACK) + else if (tlv->type == MAC_SYNC_ACK) { /*Clean the MAC_AGE_PEER flag*/ mac_msg->age_flag &= ~MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ACK, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", - mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ACK, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); } break; @@ -255,13 +256,13 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) } /* delete/add MAC list*/ - if (msg && tlv->type == MAC_SYNC_DEL) + if (msg && tlv->type == MAC_SYNC_DEL) { mac_msg->age_flag |= MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %d ifname %s, add %s vlan-id %d, op_type %d", - mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); - - if(mac_msg->age_flag == (MAC_AGE_LOCAL|MAC_AGE_PEER)) + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + + if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) { /*send mac del message to mclagsyncd.*/ del_mac_from_chip(mac_msg); @@ -276,9 +277,9 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) return 0; } } - else if (!msg && tlv->type == MAC_SYNC_ADD) + else if (!msg && tlv->type == MAC_SYNC_ADD) { - mac_msg = (struct MACMsg*) &mac_data; + mac_msg = (struct MACMsg*)&mac_data; mac_msg->fdb_type = MAC_TYPE_DYNAMIC; mac_msg->vid = ntohs(tlv->vid); sprintf(mac_msg->mac_str, "%s", tlv->mac_str); @@ -287,27 +288,27 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) mac_msg->age_flag = 0; /*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/ - if(from_mclag_intf == 0 || local_if->state == PORT_STATE_DOWN) + if (from_mclag_intf == 0 || local_if->state == PORT_STATE_DOWN) { /*Redirect the mac to peer-link*/ memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); - + /*Set MAC_AGE_LOCAL flag*/ mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); - ICCPD_LOG_DEBUG(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, add %s vlan-id %d, op_type %d", - mac_msg->age_flag,mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); } - - if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); /*ICCPD_LOG_INFO(__FUNCTION__, "add mac queue successfully");*/ /*If the port is peerlink, it must be up*/ - if(strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) + if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) { /*Send mac add message to mclagsyncd*/ - if(csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) add_mac_to_chip(mac_msg, mac_msg->fdb_type); } else @@ -317,29 +318,29 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) #if 0 mac_msg->op_type = MAC_SYNC_ACK; - if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { /*Reply mac ack message to peer, peer will clean MAC_AGE_PEER flag*/ TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, op_type %d", - mac_msg->ifname,mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); } #endif } } return 0; - } +} /***************************************** -* Tool : Add ARP Info into ARP list -* -****************************************/ + * Tool : Add ARP Info into ARP list + * + ****************************************/ void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg) { struct ARPMsg *arp_msg = NULL; - - if (!csm) + + if (!csm) { if (msg) free(msg); @@ -347,8 +348,8 @@ void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg) } if (!msg) return; - - arp_msg = (struct ARPMsg*) msg->buf; + + arp_msg = (struct ARPMsg*)msg->buf; if (arp_msg->op_type != ARP_SYNC_DEL) { TAILQ_INSERT_TAIL(&(MLACP(csm).arp_list), msg, tail); @@ -360,19 +361,19 @@ void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg) /***************************************** * ARP-Info Update * ***************************************/ -int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) +int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) { struct Msg* msg = NULL; struct ARPMsg *arp_msg = NULL, arp_data; struct LocalInterface* local_if; struct LocalInterface *peer_link_if = NULL; - struct VLAN_ID *vlan_id_list=NULL; - int set_arp_flag=0; + struct VLAN_ID *vlan_id_list = NULL; + int set_arp_flag = 0; char mac_str[18] = ""; - + if (!csm || !tlv) return -255; - + #if 1 ICCPD_LOG_INFO(__FUNCTION__, "%s: Received ARP Info," @@ -384,86 +385,86 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) #endif sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], - tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); - if(strncmp(tlv->ifname,"Vlan",4) == 0) + if (strncmp(tlv->ifname, "Vlan", 4) == 0) { peer_link_if = local_if_find_by_name(csm->peer_itf_name); - - if(!local_if_is_l3_mode(peer_link_if)) + + if (!local_if_is_l3_mode(peer_link_if)) { /* Is peer-linlk itf belong to a vlan the same as peer?*/ LIST_FOREACH(vlan_id_list, &(peer_link_if->vlan_list), port_next) { - if(!vlan_id_list->vlan_itf) + if (!vlan_id_list->vlan_itf) continue; - if(strcmp(vlan_id_list->vlan_itf->name, tlv->ifname)!=0) + if (strcmp(vlan_id_list->vlan_itf->name, tlv->ifname) != 0) continue; - if(!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) continue; - + ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ==> Find ARP itf on L3 bridge, peer-link %s of %s", __FUNCTION__, peer_link_if->name, vlan_id_list->vlan_itf->name); /* Peer-link belong to L3 vlan is alive, set the ARP info*/ - set_arp_flag=1; - + set_arp_flag = 1; + break; } } } - if(set_arp_flag == 0) + if (set_arp_flag == 0) { LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) { if (local_if->type == IF_T_PORT_CHANNEL) { - if(!local_if_is_l3_mode(local_if)) + if (!local_if_is_l3_mode(local_if)) { /* Is the L2 MLAG itf belong to a vlan the same as peer?*/ LIST_FOREACH(vlan_id_list, &(local_if->vlan_list), port_next) { - if(!vlan_id_list->vlan_itf) + if (!vlan_id_list->vlan_itf) continue; - if(strcmp(vlan_id_list->vlan_itf->name, tlv->ifname)!=0) + if (strcmp(vlan_id_list->vlan_itf->name, tlv->ifname) != 0) continue; - if(!local_if_is_l3_mode(vlan_id_list->vlan_itf)) + if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) continue; - + ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ==> Find ARP itf on L3 bridge, %s of %s", __FUNCTION__, local_if->name, vlan_id_list->vlan_itf->name); break; } - - if(vlan_id_list && local_if->po_active==1) + + if (vlan_id_list && local_if->po_active == 1) { /* Any po of L3 vlan is alive, set the ARP info*/ - set_arp_flag=1; + set_arp_flag = 1; break; - } + } } - else + else { /* Is the ARP belong to a L3 mode MLAG itf?*/ - if(strcmp(local_if->name, tlv->ifname)==0) + if (strcmp(local_if->name, tlv->ifname) == 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ==> Find ARP itf on L3 port-channel, %s", __FUNCTION__, local_if->name); - if(local_if->po_active==1) + if (local_if->po_active == 1) { /* po is alive, set the ARP info*/ - set_arp_flag=1; + set_arp_flag = 1; break; } } - else + else { continue; } @@ -471,44 +472,44 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) } } } - + /* set dynamic ARP*/ - if (set_arp_flag == 1) + if (set_arp_flag == 1) { - if (tlv->type == ARP_SYNC_ADD) + if (tlv->type == ARP_SYNC_ADD) { - if(mlacp_fsm_arp_set(tlv->ifname, ntohl(tlv->ipv4_addr), mac_str) < 0) + if (mlacp_fsm_arp_set(tlv->ifname, ntohl(tlv->ipv4_addr), mac_str) < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__,"%s: ARP set for %s %s %s", - __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); + ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP set for %s %s %s", + __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); return -1; } } - else + else { - if(mlacp_fsm_arp_del(tlv->ifname, ntohl(tlv->ipv4_addr)) < 0) + if (mlacp_fsm_arp_del(tlv->ifname, ntohl(tlv->ipv4_addr)) < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__,"%s: ARP delete for %s %s %s", - __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); + ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP delete for %s %s %s", + __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); return -1; } } - - ICCPD_LOG_DEBUG(__FUNCTION__,"%s: ARP update for %s %s %s", + + ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP update for %s %s %s", __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); } - else + else { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ==> port-channel is not alive", - __FUNCTION__); + ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ==> port-channel is not alive", + __FUNCTION__); /*TODO Set static route through peer-link or just skip it?*/ } - + /* update ARP list*/ TAILQ_FOREACH(msg, &(MLACP(csm).arp_list), tail) { - arp_msg = (struct ARPMsg*) msg->buf; - if (arp_msg->ipv4_addr == ntohl(tlv->ipv4_addr)) + arp_msg = (struct ARPMsg*)msg->buf; + if (arp_msg->ipv4_addr == ntohl(tlv->ipv4_addr)) { /*arp_msg->op_type = tlv->type;*/ sprintf(arp_msg->ifname, "%s", tlv->ifname); @@ -516,50 +517,52 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) break; } } - + /* delete/add ARP list*/ - if (msg && tlv->type == ARP_SYNC_DEL) + if (msg && tlv->type == ARP_SYNC_DEL) { TAILQ_REMOVE(&(MLACP(csm).arp_list), msg, tail); free(msg->buf); free(msg); ICCPD_LOG_INFO(__FUNCTION__, "%s: del arp queue successfully", __FUNCTION__); } - else if (!msg && tlv->type == ARP_SYNC_ADD) + else if (!msg && tlv->type == ARP_SYNC_ADD) { - arp_msg = (struct ARPMsg*) &arp_data; + arp_msg = (struct ARPMsg*)&arp_data; sprintf(arp_msg->ifname, "%s", tlv->ifname); arp_msg->ipv4_addr = ntohl(tlv->ipv4_addr); arp_msg->op_type = tlv->type; memcpy(arp_msg->mac_addr, tlv->mac_addr, ETHER_ADDR_LEN); - if (iccp_csm_init_msg(&msg, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) + if (iccp_csm_init_msg(&msg, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) { mlacp_enqueue_arp(csm, msg); ICCPD_LOG_INFO(__FUNCTION__, "%s: add arp queue successfully", __FUNCTION__); } } - + /* remove all ARP msg queue, when receive peer's ARP list at the same time*/ TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) { - arp_msg = (struct ARPMsg*) msg->buf; - if (arp_msg->ipv4_addr == ntohl(tlv->ipv4_addr)) break; + arp_msg = (struct ARPMsg*)msg->buf; + if (arp_msg->ipv4_addr == ntohl(tlv->ipv4_addr)) + break; } - - while (msg) + + while (msg) { - arp_msg = (struct ARPMsg*) msg->buf; + arp_msg = (struct ARPMsg*)msg->buf; TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); - free(msg->buf); + free(msg->buf); free(msg); TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) { - arp_msg = (struct ARPMsg*) msg->buf; - if (arp_msg->ipv4_addr == ntohl(tlv->ipv4_addr)) break; - } + arp_msg = (struct ARPMsg*)msg->buf; + if (arp_msg->ipv4_addr == ntohl(tlv->ipv4_addr)) + break; + } } - + return 0; } @@ -572,40 +575,40 @@ int mlacp_fsm_update_port_channel_info(struct CSM* csm, struct PeerInterface* peer_if = NULL; struct VLAN_ID* peer_vlan_id = NULL; int i = 0; - + if (csm == NULL || tlv == NULL ) return -1; - + LIST_FOREACH(peer_if, &(MLACP(csm).pif_list), mlacp_next) { if (peer_if->type != IF_T_PORT_CHANNEL) continue; - + if (peer_if->po_id != ntohs(tlv->agg_id)) continue; - LIST_FOREACH(peer_vlan_id, &(peer_if->vlan_list), port_next) + LIST_FOREACH(peer_vlan_id, &(peer_if->vlan_list), port_next) { peer_vlan_id->vlan_removed = 1; } - + /* Record peer info*/ peer_if->ipv4_addr = ntohl(tlv->ipv4_addr); peer_if->l3_mode = tlv->l3_mode; for (i = 0; i < ntohs(tlv->num_of_vlan_id); i++) { - peer_if_add_vlan(peer_if,ntohs(tlv->vlanData[i].vlan_id)); + peer_if_add_vlan(peer_if, ntohs(tlv->vlanData[i].vlan_id)); } - + peer_if_clean_unused_vlan(peer_if); - iccp_consistency_check(peer_if->name); - + iccp_consistency_check(peer_if->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "port channel %s info ip %s l3 mode %d", peer_if->name, show_ip_str( tlv->ipv4_addr), peer_if->l3_mode); break; - } - + } + return 0; } @@ -613,18 +616,18 @@ int mlacp_fsm_update_port_channel_info(struct CSM* csm, * Peerlink port Update * ***************************************/ int mlacp_fsm_update_peerlink_info(struct CSM* csm, - struct mLACPPeerLinkInfoTLV* tlv) -{ + struct mLACPPeerLinkInfoTLV* tlv) +{ if (csm == NULL || tlv == NULL ) return -1; - ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port info from peer"); - - if(csm->peer_link_if->type != tlv->port_type) + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port info from peer"); + + if (csm->peer_link_if->type != tlv->port_type) ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port type of peer %d is not same as local %d !", tlv->port_type, csm->peer_link_if->type); - if(tlv->port_type == IF_T_VXLAN && strncmp(csm->peer_itf_name, tlv->if_name, strlen(csm->peer_itf_name))) - ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port is vxlan port and peerlink port at peer %s is not same as local peerlink port %s !",tlv->if_name, csm->peer_itf_name); - + if (tlv->port_type == IF_T_VXLAN && strncmp(csm->peer_itf_name, tlv->if_name, strlen(csm->peer_itf_name))) + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port is vxlan port and peerlink port at peer %s is not same as local peerlink port %s !", tlv->if_name, csm->peer_itf_name); + return 0; } @@ -635,9 +638,9 @@ int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv) { if (!csm || !tlv) return -255; - + time(&csm->heartbeat_update_time); - + return 0; } @@ -648,9 +651,9 @@ int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv) { if (!csm || !tlv) return -255; - + time(&csm->peer_warm_reboot_time); - + return 0; } diff --git a/src/iccpd/src/port.c b/src/iccpd/src/port.c index d5a1baeef4c7..63791314dacf 100644 --- a/src/iccpd/src/port.c +++ b/src/iccpd/src/port.c @@ -1,25 +1,25 @@ /* -* port.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * port.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -37,30 +37,30 @@ static void ether_mac_set_addr_with_string(uint8_t* macdst, const char* macstr) unsigned long oct; int i = 0; - if(macdst == NULL || macstr == NULL) + if (macdst == NULL || macstr == NULL) return; - + memset(macdst, 0, 6); - + dupmac = strdup(macstr); - + /* tokenize */ token = strtok(dupmac, " -:"); oct = strtoul(token, NULL, 16); - if(oct > 255) + if (oct > 255) oct = 0xff; macdst[0] = oct; - for(i=1; i<6; ++i) + for (i = 1; i < 6; ++i) { token = strtok(NULL, " -:"); - if(token == NULL) + if (token == NULL) { memset(macdst, 0, 6); break; } oct = strtoul(token, NULL, 16); - if(oct > 255) + if (oct > 255) oct = 0xff; macdst[i] = oct; } @@ -71,26 +71,26 @@ static void ether_mac_set_addr_with_string(uint8_t* macdst, const char* macstr) } /* Get the Ethernet MAC Address by interface name. */ -void ether_mac_set_addr_with_if_name(char* name, uint8_t* mac) +void ether_mac_set_addr_with_if_name(char* name, uint8_t* mac) { char addr_file[64]; FILE *file_ptr = NULL; char buf[64]; - + if (!mac || !name) return; - + memset(addr_file, 0, 64); snprintf(addr_file, 63, "/sys/class/net/%s/address", name); - - if ((file_ptr = fopen(addr_file, "r"))) + + if ((file_ptr = fopen(addr_file, "r"))) { memset(buf, 0, 64); fgets(buf, 63, file_ptr); fclose(file_ptr); ether_mac_set_addr_with_string(mac, buf); - } - else + } + else { ICCPD_LOG_WARN(__FUNCTION__, "Failed to find device %s from %s", name, addr_file); } @@ -102,7 +102,7 @@ void local_if_init(struct LocalInterface* local_if) { if (local_if == NULL) return; - + memset(local_if, 0, sizeof(struct LocalInterface)); local_if->po_id = -1; local_if->po_active = 1; //always guess the po is active @@ -122,10 +122,10 @@ void local_if_init(struct LocalInterface* local_if) return; } -void vlan_info_init(struct VLAN_ID* vlan) +void vlan_info_init(struct VLAN_ID* vlan) { vlan->vid = -1; - vlan->vlan_removed= 0; + vlan->vlan_removed = 0; vlan->vlan_itf = NULL; return; @@ -137,39 +137,40 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type) struct LocalInterface* local_if = NULL; struct CSM* csm; struct If_info * cif = NULL; - - if(!ifname) + + if (!ifname) return NULL; - + if (!(sys = system_get_instance())) return NULL; - + if (ifindex < 0) return NULL; - + if ((local_if = local_if_find_by_ifindex(ifindex))) return local_if; - - if (!(local_if = (struct LocalInterface*) malloc(sizeof(struct LocalInterface)))) { + + if (!(local_if = (struct LocalInterface*)malloc(sizeof(struct LocalInterface)))) + { ICCPD_LOG_WARN(__FUNCTION__, "port ifindex = %d, malloc failed", ifindex); return NULL; } - + local_if_init(local_if); local_if->ifindex = ifindex; local_if->type = type; - if(local_if->type == IF_T_PORT_CHANNEL) + if (local_if->type == IF_T_PORT_CHANNEL) { int i; int len; len = strlen(ifname); - - for(i=0; i= '0' && ifname[i] <= '9') + + for (i = 0; i < len; ++i) + if (ifname[i] >= '0' && ifname[i] <= '9') break; - - if(i >= len) + + if (i >= len) return NULL; local_if->po_id = atoi(&ifname[i]); @@ -177,57 +178,59 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type) if (ifname) snprintf(local_if->name, MAX_L_PORT_NAME, "%s", ifname); - + switch (type) { case IF_T_PORT_CHANNEL: break; + case IF_T_PORT: break; + case IF_T_VLAN: /* do nothing currently. */ break; + case IF_T_VXLAN: /* do nothing currently. */ break; - case IF_T_BRIDGE: - break; + default: ICCPD_LOG_WARN(__FUNCTION__, "the type of local interface (%s) is not acceptable", ifname); if (local_if) free(local_if); return NULL; - } - + } + ICCPD_LOG_INFO(__FUNCTION__, - "Create a local_if = %s ifindex = %d MAC = %02x:%02x:%02x:%02x:%02x:%02x, state = %s", - ifname, local_if->ifindex, local_if->mac_addr[0], local_if->mac_addr[1], local_if->mac_addr[2], - local_if->mac_addr[3], local_if->mac_addr[4], local_if->mac_addr[5], local_if->state ? "down" : "up"); - + "Create a local_if = %s ifindex = %d MAC = %02x:%02x:%02x:%02x:%02x:%02x, state = %s", + ifname, local_if->ifindex, local_if->mac_addr[0], local_if->mac_addr[1], local_if->mac_addr[2], + local_if->mac_addr[3], local_if->mac_addr[4], local_if->mac_addr[5], local_if->state ? "down" : "up"); + LIST_INSERT_HEAD(&(sys->lif_list), local_if, system_next); /*Check the intf is peer-link? Only support PortChannel and Ethernet currently*/ /*When set peer-link, the local-if is probably not created*/ LIST_FOREACH(csm, &(sys->csm_list), next) { - if(strcmp(local_if->name, csm->peer_itf_name) == 0) + if (strcmp(local_if->name, csm->peer_itf_name) == 0) { - local_if->is_peer_link = 1; - csm->peer_link_if = local_if; - break; + local_if->is_peer_link = 1; + csm->peer_link_if = local_if; + break; } - /*check the intf is bind with csm*/ + /*check the intf is bind with csm*/ LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) { - if (strcmp(ifname, cif->name) ==0) - mlacp_bind_port_channel_to_csm(csm,ifname); - } + if (strcmp(ifname, cif->name) == 0) + mlacp_bind_port_channel_to_csm(csm, ifname); + } } - + return local_if; } -struct LocalInterface* local_if_find_by_name(const char* ifname) +struct LocalInterface* local_if_find_by_name(const char* ifname) { struct System* sys = NULL; struct LocalInterface* local_if = NULL; @@ -247,34 +250,34 @@ struct LocalInterface* local_if_find_by_name(const char* ifname) return NULL; } -struct LocalInterface* local_if_find_by_ifindex(int ifindex) +struct LocalInterface* local_if_find_by_ifindex(int ifindex) { struct System* sys = NULL; struct LocalInterface* local_if = NULL; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) return NULL; - LIST_FOREACH(local_if, &(sys->lif_list), system_next) + LIST_FOREACH(local_if, &(sys->lif_list), system_next) { - if(local_if->ifindex == ifindex) + if (local_if->ifindex == ifindex) return local_if; } return NULL; } -struct LocalInterface* local_if_find_by_po_id(int po_id) +struct LocalInterface* local_if_find_by_po_id(int po_id) { struct System* sys = NULL; struct LocalInterface* local_if = NULL; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) return NULL; - LIST_FOREACH(local_if, &(sys->lif_list), system_next) + LIST_FOREACH(local_if, &(sys->lif_list), system_next) { - if(local_if->type == IF_T_PORT_CHANNEL && local_if->po_id == po_id) + if (local_if->type == IF_T_PORT_CHANNEL && local_if->po_id == po_id) return local_if; } @@ -286,16 +289,16 @@ static void local_if_vlan_remove(struct LocalInterface *lif_vlan) struct System *sys = NULL; struct LocalInterface *lif = NULL; struct VLAN_ID *vlan = NULL; - - if ((sys = system_get_instance()) != NULL) + + if ((sys = system_get_instance()) != NULL) { LIST_FOREACH(lif, &(sys->lif_list), system_next) { LIST_FOREACH(vlan, &(lif->vlan_list), port_next) { - if(lif_vlan != vlan->vlan_itf) + if (lif_vlan != vlan->vlan_itf) continue; - + vlan->vlan_itf = NULL; } } @@ -309,18 +312,20 @@ static void local_if_po_remove(struct LocalInterface *lif_po) struct System *sys = NULL; struct CSM *csm = NULL; struct LocalInterface *lif = NULL; - + /* remove all po member*/ - if ((sys = system_get_instance()) != NULL) + if ((sys = system_get_instance()) != NULL) { csm = lif_po->csm; - if (csm) + if (csm) { LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) { - if (lif->type != IF_T_PORT) continue; - if (lif->po_id != lif_po->po_id) continue; - + if (lif->type != IF_T_PORT) + continue; + if (lif->po_id != lif_po->po_id) + continue; + mlacp_unbind_local_if(lif); } } @@ -330,7 +335,7 @@ static void local_if_po_remove(struct LocalInterface *lif_po) } static void local_if_remove(struct LocalInterface *lif) -{ +{ mlacp_unbind_local_if(lif); lif->po_id = -1; @@ -342,36 +347,38 @@ void local_if_destroy(char *ifname) struct LocalInterface* lif = NULL; struct CSM *csm = NULL; struct System *sys = NULL; - + if (!(sys = system_get_instance())) return; - + lif = local_if_find_by_name(ifname); - if (!lif) return; - + if (!lif) + return; + ICCPD_LOG_WARN(__FUNCTION__, "destroy interface %s, %d\n", lif->name, lif->ifindex); - + if (lif->type == IF_T_VLAN) local_if_vlan_remove(lif); else if (lif->type == IF_T_PORT_CHANNEL) local_if_po_remove(lif); else - local_if_remove(lif); - + local_if_remove(lif); + csm = lif->csm; if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) goto to_mlacp_purge; else goto to_sys_purge; - -to_sys_purge: + + to_sys_purge: /* sys purge */ LIST_REMOVE(lif, system_next); - if (lif->csm) LIST_REMOVE(lif, mlacp_next); + if (lif->csm) + LIST_REMOVE(lif, mlacp_next); LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next); return; - -to_mlacp_purge: + + to_mlacp_purge: /* sys & mlacp purge */ LIST_REMOVE(lif, system_next); LIST_REMOVE(lif, mlacp_next); @@ -380,16 +387,16 @@ void local_if_destroy(char *ifname) return; } -int local_if_is_l3_mode(struct LocalInterface* local_if) +int local_if_is_l3_mode(struct LocalInterface* local_if) { int ret = 0; if (local_if == NULL) return 0; - - if (local_if->ipv4_addr !=0) + + if (local_if->ipv4_addr != 0) ret = 1; - + return ret; } @@ -398,12 +405,12 @@ void local_if_change_flag_clear(void) struct System* sys = NULL; struct LocalInterface* lif = NULL; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) return; - LIST_FOREACH(lif, &(sys->lif_list), system_next) + LIST_FOREACH(lif, &(sys->lif_list), system_next) { - if (lif->changed == 1) + if (lif->changed == 1) { lif->changed = 0; } @@ -416,21 +423,22 @@ void local_if_purge_clear(void) { struct System* sys = NULL; struct LocalInterface* lif = NULL; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return; - + /* destroy purge if*/ while (!LIST_EMPTY(&(sys->lif_purge_list))) { lif = LIST_FIRST(&(sys->lif_purge_list)); ICCPD_LOG_DEBUG(__FUNCTION__, "purge %s", lif->name); LIST_REMOVE(lif, system_purge_next); - if (lif->mlacp_purge_next.le_next!=0 && lif->mlacp_purge_next.le_prev!=0) + if (lif->mlacp_purge_next.le_next != 0 && lif->mlacp_purge_next.le_prev != 0) LIST_REMOVE(lif, mlacp_purge_next); local_if_del_all_vlan(lif); free(lif); } + LIST_INIT(&(sys->lif_purge_list)); return; @@ -440,9 +448,9 @@ void local_if_finalize(struct LocalInterface* lif) { if (lif == NULL) return; - + local_if_del_all_vlan(lif); - + free(lif); return; @@ -452,35 +460,35 @@ struct PeerInterface* peer_if_create(struct CSM* csm, int peer_if_number, int type) { struct PeerInterface* peer_if = NULL; - + /* check csm*/ if (csm == NULL) return NULL; - + /* check id*/ - if (peer_if_number < 0) + if (peer_if_number < 0) { ICCPD_LOG_WARN(__FUNCTION__, "peer interface id < 0"); return NULL; } - + /* check type*/ - if (type != IF_T_PORT && type != IF_T_PORT_CHANNEL) + if (type != IF_T_PORT && type != IF_T_PORT_CHANNEL) { ICCPD_LOG_WARN(__FUNCTION__, "the type(%) of peer interface(%d) is not acceptable", type, peer_if_number); return NULL; } - + /* create a new peer if*/ - if ((peer_if = (struct PeerInterface*) malloc(sizeof(struct PeerInterface))) == NULL) + if ((peer_if = (struct PeerInterface*)malloc(sizeof(struct PeerInterface))) == NULL) { ICCPD_LOG_WARN(__FUNCTION__, "peer port id = %d, malloc failed", peer_if_number); return NULL; } memset(peer_if, 0, sizeof(struct PeerInterface)); - + if (type == IF_T_PORT) { peer_if->ifindex = peer_if_number; @@ -492,13 +500,13 @@ struct PeerInterface* peer_if_create(struct CSM* csm, peer_if->ifindex = peer_if_number; peer_if->type = IF_T_PORT_CHANNEL; } - + LIST_INSERT_HEAD(&(MLACP(csm).pif_list), peer_if, mlacp_next); - + return peer_if; } -struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name) +struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name) { struct System* sys = NULL; struct PeerInterface* peer_if = NULL; @@ -508,13 +516,13 @@ struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name) if (csm == NULL) return NULL; - + LIST_FOREACH(peer_if, &(csm->app_csm.mlacp.pif_list), mlacp_next) { if (strcmp(peer_if->name, name) == 0) return peer_if; } - + return NULL; } @@ -538,7 +546,7 @@ void peer_if_destroy(struct PeerInterface* pif) { ICCPD_LOG_WARN(__FUNCTION__, "destroy peer's interface %s, %d\n", pif->name, pif->ifindex); - + /* destroy if*/ LIST_REMOVE(pif, mlacp_next); peer_if_del_all_vlan(pif); @@ -547,31 +555,31 @@ void peer_if_destroy(struct PeerInterface* pif) return; } -int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) +int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) { struct VLAN_ID *vlan = NULL; char vlan_name[16] = ""; sprintf(vlan_name, "Vlan%d", vid); - + /* traverse 1 time */ LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) { - if(vlan->vid == vid) + if (vlan->vid == vid) break; } - + if (!vlan) { - vlan = (struct VLAN_ID*) malloc(sizeof(struct VLAN_ID)); - if(!vlan) + vlan = (struct VLAN_ID*)malloc(sizeof(struct VLAN_ID)); + if (!vlan) return -1; - + ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d on %s", vid, local_if->name); local_if->port_config_sync = 1; LIST_INSERT_HEAD(&(local_if->vlan_list), vlan, port_next); } - + vlan_info_init(vlan); vlan->vid = vid; vlan->vlan_removed = 0; @@ -579,24 +587,24 @@ int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) return 0; } -void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid) +void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid) { struct VLAN_ID *vlan = NULL; - + /* traverse 1 time */ LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) { - if(vlan->vid == vid) + if (vlan->vid == vid) break; } - - if(vlan != NULL) + + if (vlan != NULL) { LIST_REMOVE(vlan, port_next); free(vlan); local_if->port_config_sync = 1; } - + ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d on %s", vid, local_if->name); return; @@ -605,7 +613,7 @@ void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid) void local_if_del_all_vlan(struct LocalInterface* lif) { struct VLAN_ID* vlan = NULL; - + while (!LIST_EMPTY(&(lif->vlan_list))) { vlan = LIST_FIRST(&(lif->vlan_list)); @@ -618,13 +626,13 @@ void local_if_del_all_vlan(struct LocalInterface* lif) } /* Add VLAN from peer-link*/ -int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) +int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) { struct VLAN_ID *peer_vlan = NULL; char vlan_name[16] = ""; sprintf(vlan_name, "Vlan%d", vlan_id); - + /* traverse 1 time */ LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) { @@ -635,16 +643,16 @@ int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) } } - if(!peer_vlan) + if (!peer_vlan) { - peer_vlan = (struct VLAN_ID*) malloc(sizeof(struct VLAN_ID)); - if(!peer_vlan) + peer_vlan = (struct VLAN_ID*)malloc(sizeof(struct VLAN_ID)); + if (!peer_vlan) return -1; - + ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d from peer's %s", vlan_id, peer_if->name); LIST_INSERT_HEAD(&(peer_if->vlan_list), peer_vlan, port_next); } - + vlan_info_init(peer_vlan); peer_vlan->vid = vlan_id; peer_vlan->vlan_removed = 0; @@ -653,7 +661,7 @@ int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) } /* Used by sync update*/ -int peer_if_clean_unused_vlan(struct PeerInterface* peer_if) +int peer_if_clean_unused_vlan(struct PeerInterface* peer_if) { struct VLAN_ID *peer_vlan = NULL; struct VLAN_ID *peer_vlan_next = NULL; @@ -661,29 +669,29 @@ int peer_if_clean_unused_vlan(struct PeerInterface* peer_if) /* traverse 1 time */ LIST_FOREACH(peer_vlan_next, &(peer_if->vlan_list), port_next) { - if(peer_vlan != NULL) + if (peer_vlan != NULL) { ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); LIST_REMOVE(peer_vlan, port_next); free(peer_vlan); peer_vlan = NULL; - + } if (peer_vlan_next->vlan_removed == 1) peer_vlan = peer_vlan_next; } - - if(peer_vlan != NULL) + + if (peer_vlan != NULL) { ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); LIST_REMOVE(peer_vlan, port_next); free(peer_vlan); } - + return 0; } -int set_sys_arp_accept_flag(char* ifname, int flag) +int set_sys_arp_accept_flag(char* ifname, int flag) { FILE *file_ptr = NULL; char cmd[64]; @@ -693,7 +701,7 @@ int set_sys_arp_accept_flag(char* ifname, int flag) memset(arp_file, 0, 64); snprintf(arp_file, 63, "/proc/sys/net/ipv4/conf/%s/arp_accept", ifname); - if (!(file_ptr = fopen(arp_file, "r"))) + if (!(file_ptr = fopen(arp_file, "r"))) { ICCPD_LOG_DEBUG(__func__, "Failed to find device %s from %s", ifname, arp_file); return result; @@ -702,7 +710,7 @@ int set_sys_arp_accept_flag(char* ifname, int flag) fgets(buf, sizeof(buf), file_ptr); if (atoi(buf) == flag) result = 0; - else + else { memset(cmd, 0, 64); snprintf(cmd, 63, "echo %d > /proc/sys/net/ipv4/conf/%s/arp_accept", flag, ifname); diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c index cec97accac5a..6ef15f17014c 100644 --- a/src/iccpd/src/scheduler.c +++ b/src/iccpd/src/scheduler.c @@ -1,25 +1,25 @@ /* -* scheduler.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * scheduler.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include #include @@ -43,10 +43,10 @@ #include "../include/iccp_netlink.h" /****************************************************** - * - * Global Variable - * - ******************************************************/ +* +* Global Variable +* +******************************************************/ static int session_conn_thread_lock(pthread_mutex_t *conn_mutex) { @@ -55,7 +55,7 @@ static int session_conn_thread_lock(pthread_mutex_t *conn_mutex) static int session_conn_thread_trylock(pthread_mutex_t *conn_mutex) { - return 0 ;/*pthread_mutex_trylock(conn_mutex);*/ + return 0; /*pthread_mutex_trylock(conn_mutex);*/ } static int session_conn_thread_unlock(pthread_mutex_t *conn_mutex) @@ -65,13 +65,13 @@ static int session_conn_thread_unlock(pthread_mutex_t *conn_mutex) static void heartbeat_check(struct CSM *csm) { - if (csm->heartbeat_update_time == 0) + if (csm->heartbeat_update_time == 0) { time(&csm->heartbeat_update_time); return; } - - if( (time(NULL) - csm->heartbeat_update_time) > HEARTBEAT_TIMEOUT_SEC) + + if ( (time(NULL) - csm->heartbeat_update_time) > HEARTBEAT_TIMEOUT_SEC) { /* hearbeat timeout*/ ICCPD_LOG_INFO(__FUNCTION__, "iccpd connection timeout (heartbeat)"); @@ -83,7 +83,7 @@ static void heartbeat_check(struct CSM *csm) static void heartbeat_update(struct CSM *csm) { - if(csm->sock_fd > 0) + if (csm->sock_fd > 0) { heartbeat_check(csm); } @@ -96,10 +96,10 @@ static int scheduler_transit_fsm() { struct CSM* csm = NULL; struct System* sys = NULL; - + if ((sys = system_get_instance()) == NULL) return -1; - + LIST_FOREACH(csm, &(sys->csm_list), next) { heartbeat_update(csm); @@ -108,39 +108,40 @@ static int scheduler_transit_fsm() mlacp_fsm_transit(csm); if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE && (time(NULL) - sys->csm_trans_time) >= 60) - { + { iccp_get_fdb_change_from_syncd(); sys->csm_trans_time = time(NULL); } } - + local_if_change_flag_clear(); local_if_purge_clear(); - + return 1; } /* Receive packets call back function */ -int scheduler_csm_read_callback(struct CSM* csm) +int scheduler_csm_read_callback(struct CSM* csm) { - struct Msg* msg = NULL; + struct Msg* msg = NULL; /*peer message*/ char *peer_msg = g_csm_buf; LDPHdr* ldp_hdr = (LDPHdr*)peer_msg; char* data = &peer_msg[sizeof(LDPHdr)]; size_t data_len = 0; size_t pos = 0; - int recv_len=0, len=0, retval; - + int recv_len = 0, len = 0, retval; + if (csm->sock_fd <= 0) return -1; - + memset(peer_msg, 0, CSM_BUFFER_SIZE); - + recv_len = 0; - while(recv_len != sizeof(LDPHdr)) + + while (recv_len != sizeof(LDPHdr)) { - len = recv(csm->sock_fd, peer_msg+recv_len, sizeof(LDPHdr)-recv_len, 0); + len = recv(csm->sock_fd, peer_msg + recv_len, sizeof(LDPHdr) - recv_len, 0); if (len == -1) { perror("recv(). Error"); @@ -154,17 +155,19 @@ int scheduler_csm_read_callback(struct CSM* csm) recv_len += len; /*usleep(100);*/ } - + data_len = ntohs(ldp_hdr->msg_len) - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS; pos = 0; - while(data_len > 0) + + while (data_len > 0) { recv_len = recv(csm->sock_fd, &data[pos], data_len, 0); - if (recv_len == -1) { + if (recv_len == -1) + { perror("continue recv(). Error"); goto recv_err; - } - else if (recv_len == 0) + } + else if (recv_len == 0) { ICCPD_LOG_INFO(__FUNCTION__, "Peer disconnect"); goto recv_err; @@ -173,19 +176,19 @@ int scheduler_csm_read_callback(struct CSM* csm) pos += recv_len; /*usleep(100);*/ } - + retval = iccp_csm_init_msg(&msg, peer_msg, ntohs(ldp_hdr->msg_len) + MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS); - if (retval == 0) + if (retval == 0) { iccp_csm_enqueue_msg(csm, msg); ++csm->icc_msg_in_count; - } + } else ++csm->i_msg_in_count; - + return 1; - -recv_err: + + recv_err: scheduler_session_disconnect_handler(csm); return -1; } @@ -199,96 +202,98 @@ int scheduler_server_accept() struct System* sys = NULL; struct sockaddr_in client_addr; socklen_t addr_len; - - if ((sys = system_get_instance()) == NULL ) + + if ((sys = system_get_instance()) == NULL ) { return -1; } - if(sys->server_fd <= 0) + if (sys->server_fd <= 0) { return -1; } - + addr_len = sizeof(struct sockaddr_in); - new_fd = accept(sys->server_fd, (struct sockaddr *) &client_addr, &addr_len); - if (new_fd == -1) + new_fd = accept(sys->server_fd, (struct sockaddr *)&client_addr, &addr_len); + if (new_fd == -1) { goto reject_client; } - else + else { csm = system_get_csm_by_peer_ip(inet_ntoa(client_addr.sin_addr)); - if(!csm) + if (!csm) { /* can't find csm with peer ip*/ ICCPD_LOG_INFO(__FUNCTION__, "csm null with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); goto reject_client; } - - if(csm->sock_fd > 0) + + if (csm->sock_fd > 0) { /* peer already connected*/ ICCPD_LOG_INFO(__FUNCTION__, "csm sock is connected with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); goto reject_client; } - - if((ret = scheduler_check_csm_config(csm)) < 0) + + if ((ret = scheduler_check_csm_config(csm)) < 0) { /* csm config error*/ ICCPD_LOG_INFO(__FUNCTION__, "csm config error with peer ip [%s]", inet_ntoa(client_addr.sin_addr)); goto reject_client; } } - + /* Accept*/ goto accept_client; - -reject_client: - if(new_fd >= 0) close(new_fd); + + reject_client: + if (new_fd >= 0) + close(new_fd); return -1; -accept_client: + accept_client: session_conn_thread_lock(&csm->conn_mutex); - ICCPD_LOG_INFO(__FUNCTION__, "Server Accept, SocketFD [%d], %p", new_fd, csm); - + ICCPD_LOG_INFO(__FUNCTION__, "Server Accept, SocketFD [%d], %p", new_fd, csm); + struct epoll_event event; int err; event.data.fd = new_fd; event.events = EPOLLIN; - err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, new_fd, &event); - if(err) + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, new_fd, &event); + if (err) { session_conn_thread_unlock(&csm->conn_mutex); - goto reject_client; + goto reject_client; } - + csm->sock_fd = new_fd; csm->current_state = ICCP_NONEXISTENT; - FD_SET(new_fd, &(sys->readfd)); - sys->readfd_count ++; + FD_SET(new_fd, &(sys->readfd)); + sys->readfd_count++; session_conn_thread_unlock(&csm->conn_mutex); return 0; } void iccp_get_start_type(struct System* sys) { - FILE* fp; - memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + FILE* fp; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); fp = fopen("/proc/cmdline", "r"); - if (!fp) + if (!fp) { - ICCPD_LOG_DEBUG(__FUNCTION__,"Error: Can't open file /proc/cmdline!"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Error: Can't open file /proc/cmdline!"); return; } fread(g_csm_buf, CSM_BUFFER_SIZE, 1, fp); (void)fclose(fp); - - if(strstr(g_csm_buf, "SONIC_BOOT_TYPE=warm")) + + if (strstr(g_csm_buf, "SONIC_BOOT_TYPE=warm")) sys->warmboot_start = WARM_REBOOT; - return; + return; } /* scheduler initialization */ @@ -308,8 +313,8 @@ void scheduler_init() /*Get kernel ARP info */ iccp_arp_get_init(); - - if(iccp_connect_syncd() < 0) + + if (iccp_connect_syncd() < 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, syncd info socket connect fail", __FUNCTION__, __LINE__); @@ -322,59 +327,60 @@ void scheduler_init() if (mclagd_ctl_sock_create() < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclagd ctl info socket connect fail", + ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclagd ctl info socket connect fail", __FUNCTION__, __LINE__); } - + return; } -extern int mlacp_prepare_for_warm_reboot(struct CSM* csm,char* buf, size_t max_buf_size); +extern int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_size); void mlacp_sync_send_warmboot_flag() { struct System* sys = NULL; struct CSM* csm = NULL; int msg_len = 0; - - if((sys = system_get_instance()) == NULL) - return; - + + if ((sys = system_get_instance()) == NULL) + return; + LIST_FOREACH(csm, &(sys->csm_list), next) { - if(MLACP(csm).current_state==MLACP_STATE_EXCHANGE) + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { memset(g_csm_buf, 0, CSM_BUFFER_SIZE); msg_len = mlacp_prepare_for_warm_reboot(csm, g_csm_buf, CSM_BUFFER_SIZE); iccp_csm_send(csm, g_csm_buf, msg_len); } - } - + } + return; } int iccp_receive_signal_handler(struct System* sys) { char ctrl_byte; - int err = 0; - + int err = 0; + err = read(sys->sig_pipe_r, &ctrl_byte, 1); if (err == -1) { - ICCPD_LOG_DEBUG(__FUNCTION__,"Read sig_pipe_r fail !"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Read sig_pipe_r fail !"); return err; - } + } - switch(ctrl_byte) + switch (ctrl_byte) { case 'w': - /*send packet to peer*/ + /*send packet to peer*/ mlacp_sync_send_warmboot_flag(); sys->warmboot_exit = WARM_REBOOT; break; + default: break; } - + return 0; } @@ -385,10 +391,10 @@ void scheduler_loop() if ((sys = system_get_instance()) == NULL) return; - - while(1) - { - if(sys->sync_fd <= 0) + + while (1) + { + if (sys->sync_fd <= 0) { iccp_connect_syncd(); } @@ -396,11 +402,11 @@ void scheduler_loop() /*handle socket slelect event ,If no message received, it will block 0.1s*/ iccp_handle_events(sys); /*csm, app state machine transit */ - scheduler_transit_fsm(); + scheduler_transit_fsm(); if (sys->warmboot_exit == WARM_REBOOT) { - ICCPD_LOG_DEBUG(__FUNCTION__, "EXIT ......"); + ICCPD_LOG_DEBUG(__FUNCTION__, "EXIT ......"); return; } } @@ -418,7 +424,7 @@ int mlacp_sync_with_kernel_callback() struct CSM* csm = NULL; struct LocalInterface* local_if = NULL; - if((sys = system_get_instance()) == NULL) + if ((sys = system_get_instance()) == NULL) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); goto out; @@ -430,40 +436,41 @@ int mlacp_sync_with_kernel_callback() /* Sync MLAG po state with kernel*/ LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) { - if(local_if->type == IF_T_PORT_CHANNEL) + if (local_if->type == IF_T_PORT_CHANNEL) { /* sync system info from one port-channel device*/ - if(memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) + if (memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) { - memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); - MLACP(csm).system_config_changed = 1; - break; + memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); + MLACP(csm).system_config_changed = 1; + break; } } } } - -out: + + out: return 0; } /* Scheduler start while loop */ -void scheduler_start() +void scheduler_start() { - mlacp_sync_with_kernel_callback(); - + /*mlacp_sync_with_kernel_callback();*/ + scheduler_loop(); return; } /* Scheduler tear down */ -void scheduler_finalize() { +void scheduler_finalize() +{ struct System* sys = NULL; if ((sys = system_get_instance()) == NULL) return; - + syncd_info_close(); log_finalize(); @@ -477,44 +484,44 @@ void session_client_conn_handler(struct CSM *csm) { struct System* sys = NULL; struct sockaddr_in peer_addr; - int connFd=-1, connStat=-1; + int connFd = -1, connStat = -1; struct timeval con_tv; socklen_t len = sizeof(con_tv); - + /* Lock the thread*/ session_conn_thread_lock(&csm->conn_mutex); - + sys = system_get_instance(); - if(!sys) + if (!sys) goto conn_fail; - + /* Create sock*/ connFd = socket(PF_INET, SOCK_STREAM, 0); bzero(&peer_addr, sizeof(peer_addr)); peer_addr.sin_family = PF_INET; peer_addr.sin_port = htons(ICCP_TCP_PORT); peer_addr.sin_addr.s_addr = inet_addr(csm->peer_ip); - if (connFd == -1) + if (connFd == -1) { ICCPD_LOG_DEBUG(__FUNCTION__, "Peer IP:%s Socket FD creation failed.", csm->peer_ip); goto conn_fail; } - + /* Set connect timeout secs*/ con_tv.tv_sec = 0; - con_tv.tv_usec = CONNECT_TIMEOUT_MSEC*1000; - if (setsockopt(connFd, SOL_SOCKET, SO_SNDTIMEO, &con_tv, len) == -1) + con_tv.tv_usec = CONNECT_TIMEOUT_MSEC * 1000; + if (setsockopt(connFd, SOL_SOCKET, SO_SNDTIMEO, &con_tv, len) == -1) { ICCPD_LOG_INFO(__FUNCTION__, "Set socket timeout fail"); } - + /* Try conn*/ ICCPD_LOG_INFO(__FUNCTION__, "Connecting. peer ip = [%s], %p", csm->peer_ip, csm); - connStat = connect(connFd, (struct sockaddr*) &(peer_addr), sizeof(peer_addr)); + connStat = connect(connFd, (struct sockaddr*)&(peer_addr), sizeof(peer_addr)); ICCPD_LOG_INFO(__FUNCTION__, "Connection. fd = [%d], status = [%d], %p", connFd, connStat, csm); - + if (connStat != 0) { /* Conn Fail*/ @@ -527,9 +534,9 @@ void session_client_conn_handler(struct CSM *csm) int err; event.data.fd = connFd; event.events = EPOLLIN; - err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, connFd, &event); - if(err) - goto conn_fail; + err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, connFd, &event); + if (err) + goto conn_fail; csm->sock_fd = connFd; FD_SET(connFd, &(sys->readfd)); sys->readfd_count++; @@ -537,13 +544,13 @@ void session_client_conn_handler(struct CSM *csm) goto conn_ok; } -conn_fail: - if(connFd >= 0) + conn_fail: + if (connFd >= 0) { csm->sock_fd = -1; close(connFd); } -conn_ok: + conn_ok: time(&csm->connTimePrev); session_conn_thread_unlock(&csm->conn_mutex); return; @@ -555,54 +562,54 @@ int scheduler_prepare_session(struct CSM* csm) int ret = -1; uint32_t local_ip = 0; uint32_t peer_ip = 0; - + /* Init time_t*/ - if (csm->connTimePrev == 0) + if (csm->connTimePrev == 0) { time(&csm->connTimePrev); } - + /* Don't conn to svr continously*/ - if((time(NULL) - csm->connTimePrev) < CONNECT_INTERVAL_SEC) + if ((time(NULL) - csm->connTimePrev) < CONNECT_INTERVAL_SEC) { goto no_time_update; } - + /* Already conn?*/ - if(csm->sock_fd > 0) + if (csm->sock_fd > 0) { goto time_update; } - + if ((ret = scheduler_check_csm_config(csm)) < 0) goto time_update; - + /* Who is client*/ local_ip = inet_addr(csm->sender_ip); peer_ip = inet_addr(csm->peer_ip); - if(local_ip > peer_ip) + if (local_ip > peer_ip) { goto time_update; } - else if(local_ip == peer_ip) + else if (local_ip == peer_ip) { ICCPD_LOG_WARN("connect", "Sender IP is as the same as the peer IP. " "This must be fixed before connection is built."); goto time_update; } - - if(session_conn_thread_trylock(&csm->conn_mutex) == 0) + + if (session_conn_thread_trylock(&csm->conn_mutex) == 0) { session_client_conn_handler(csm); session_conn_thread_unlock(&csm->conn_mutex); } -time_update: + time_update: time(&csm->connTimePrev); return 0; - -no_time_update: + + no_time_update: return 0; } @@ -612,40 +619,40 @@ void scheduler_server_sock_init() int optval = 1; struct System* sys = NULL; struct sockaddr_in svr_addr; - + if ((sys = system_get_instance()) == NULL) return; - + sys->server_fd = socket(PF_INET, SOCK_STREAM, 0); bzero(&(svr_addr), sizeof(svr_addr)); svr_addr.sin_family = PF_INET; svr_addr.sin_port = htons(ICCP_TCP_PORT); svr_addr.sin_addr.s_addr = INADDR_ANY; - - if (sys->server_fd == -1) + + if (sys->server_fd == -1) { ICCPD_LOG_ERR(__FUNCTION__, "Server Socket FD creation failed."); return; } - + if (setsockopt(sys->server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) { - ICCPD_LOG_INFO(__FUNCTION__,"Set socket option failed. Error"); + ICCPD_LOG_INFO(__FUNCTION__, "Set socket option failed. Error"); /*return;*/ } - if (bind(sys->server_fd, (struct sockaddr*) &(svr_addr), sizeof(svr_addr)) < 0) + if (bind(sys->server_fd, (struct sockaddr*)&(svr_addr), sizeof(svr_addr)) < 0) { - ICCPD_LOG_INFO(__FUNCTION__,"Bind socket failed. Error"); + ICCPD_LOG_INFO(__FUNCTION__, "Bind socket failed. Error"); return; } - - if (listen(sys->server_fd, MAX_ACCEPT_CONNETIONS) == -1) + + if (listen(sys->server_fd, MAX_ACCEPT_CONNETIONS) == -1) { - ICCPD_LOG_INFO(__FUNCTION__,"Listen failed. Error"); + ICCPD_LOG_INFO(__FUNCTION__, "Listen failed. Error"); return; } - + ICCPD_LOG_INFO(__FUNCTION__, "Server socket init done."); return; @@ -654,7 +661,7 @@ void scheduler_server_sock_init() int iccp_get_server_sock_fd() { struct System* sys = NULL; - + if ((sys = system_get_instance()) == NULL) return 0; @@ -667,14 +674,14 @@ int scheduler_check_csm_config(struct CSM* csm) int ret = 1; struct LocalInterface* lif = NULL; struct System* sys = NULL; - - if((sys = system_get_instance()) == NULL) + + if ((sys = system_get_instance()) == NULL) return -1; - + if (csm == NULL ) return -1; - - if(csm->mlag_id <= 0) + + if (csm->mlag_id <= 0) ret = -1; else if (strlen(csm->peer_itf_name) <= 0) ret = -1; @@ -682,59 +689,59 @@ int scheduler_check_csm_config(struct CSM* csm) ret = -1; else if (strlen(csm->sender_ip) <= 0) ret = -1; - else if ((lif=local_if_find_by_name(csm->peer_itf_name)) == NULL) - ret = -1; + else if ((lif = local_if_find_by_name(csm->peer_itf_name)) == NULL) + ret = -1; else { lif->is_peer_link = 1; csm->peer_link_if = lif; } - - if(ret == -1) - ICCPD_LOG_INFO(__FUNCTION__, "mclag config is not complete or conflicting, please check!"); + + if (ret == -1) + ICCPD_LOG_INFO(__FUNCTION__, "mclag config is not complete or conflicting, please check!"); /* Decide STP role*/ iccp_csm_stp_role_count(csm); - - return ret; + + return ret; } -int scheduler_unregister_sock_read_event_callback(struct CSM* csm) +int scheduler_unregister_sock_read_event_callback(struct CSM* csm) { struct System* sys = NULL; - + if ((sys = system_get_instance()) == NULL ) return -1; - - if (csm == NULL ) + + if (csm == NULL ) { return -2; } FD_CLR(csm->sock_fd, &(sys->readfd)); - + return 0; } void scheduler_session_disconnect_handler(struct CSM* csm) { struct System* sys = NULL; - + if ((sys = system_get_instance()) == NULL ) - return ; + return; + + struct epoll_event event; - struct epoll_event event; - if (csm == NULL) - return ; - + return; + session_conn_thread_lock(&csm->conn_mutex); scheduler_unregister_sock_read_event_callback(csm); - if(csm->sock_fd > 0) + if (csm->sock_fd > 0) { event.data.fd = csm->sock_fd; event.events = EPOLLIN; epoll_ctl(sys->epoll_fd, EPOLL_CTL_DEL, csm->sock_fd, &event); - + close(csm->sock_fd); csm->sock_fd = -1; } @@ -744,6 +751,6 @@ void scheduler_session_disconnect_handler(struct CSM* csm) iccp_csm_status_reset(csm, 0); time(&csm->connTimePrev); session_conn_thread_unlock(&csm->conn_mutex); - + return; } diff --git a/src/iccpd/src/system.c b/src/iccpd/src/system.c index c525609b8c36..b6631d3be66f 100644 --- a/src/iccpd/src/system.c +++ b/src/iccpd/src/system.c @@ -1,25 +1,25 @@ /* -* system.c -* -* Copyright(c) 2016-2019 Nephos/Estinet. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License along with -* this program; if not, see . -* -* The full GNU General Public License is included in this distribution in -* the file called "COPYING". -* -* Maintainer: jianjun, grace Li from nephos -*/ + * system.c + * + * Copyright(c) 2016-2019 Nephos/Estinet. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see . + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Maintainer: jianjun, grace Li from nephos + */ #include @@ -29,29 +29,29 @@ #include "../include/scheduler.h" /* Singleton */ -struct System* system_get_instance() +struct System* system_get_instance() { static struct System* sys = NULL; - - if (sys == NULL ) + + if (sys == NULL ) { - sys = (struct System*) malloc(sizeof(struct System)); - if (sys == NULL ) + sys = (struct System*)malloc(sizeof(struct System)); + if (sys == NULL ) { - return NULL ; + return NULL; } system_init(sys); } - + return sys; } /* System instance initialization */ -void system_init(struct System* sys) +void system_init(struct System* sys) { if (sys == NULL ) return; - + sys->server_fd = -1; sys->sync_fd = -1; sys->sync_ctrl_fd = -1; @@ -63,7 +63,7 @@ void system_init(struct System* sys) LIST_INIT(&(sys->csm_list)); LIST_INIT(&(sys->lif_list)); LIST_INIT(&(sys->lif_purge_list)); - + sys->log_file_path = strdup("/var/log/iccpd.log"); sys->cmd_file_path = strdup("/var/run/iccpd/iccpd.vty"); sys->config_file_path = strdup("/etc/iccpd/iccpd.conf"); @@ -74,30 +74,30 @@ void system_init(struct System* sys) sys->readfd_count = 0; sys->csm_trans_time = 0; sys->need_sync_team_again = 0; - sys->need_sync_netlink_again = 0; + sys->need_sync_netlink_again = 0; scheduler_server_sock_init(); iccp_system_init_netlink_socket(); iccp_init_netlink_event_fd(sys); } /* System instance tear down */ -void system_finalize() +void system_finalize() { struct System* sys = NULL; struct CSM* csm = NULL; struct LocalInterface* local_if = NULL; - + if ((sys = system_get_instance()) == NULL ) return; - + ICCPD_LOG_INFO(__FUNCTION__, "System resource pool is destructing."); - + while (!LIST_EMPTY(&(sys->csm_list))) { csm = LIST_FIRST(&(sys->csm_list)); iccp_csm_finalize(csm); } - + /* Release all port objects */ while (!LIST_EMPTY(&(sys->lif_list))) { @@ -105,15 +105,16 @@ void system_finalize() LIST_REMOVE(local_if, system_next); local_if_finalize(local_if); } + while (!LIST_EMPTY(&(sys->lif_purge_list))) { local_if = LIST_FIRST(&(sys->lif_purge_list)); LIST_REMOVE(local_if, system_purge_next); local_if_finalize(local_if); } - + iccp_system_dinit_netlink_socket(); - + if (sys->log_file_path != NULL ) free(sys->log_file_path); if (sys->cmd_file_path != NULL ) @@ -122,22 +123,22 @@ void system_finalize() free(sys->config_file_path); if (sys->pid_file_fd > 0) close(sys->pid_file_fd); - if(sys->server_fd > 0) + if (sys->server_fd > 0) close(sys->server_fd); - if(sys->sync_fd > 0) + if (sys->sync_fd > 0) close(sys->sync_fd); - if(sys->sync_ctrl_fd > 0) + if (sys->sync_ctrl_fd > 0) close(sys->sync_ctrl_fd); - if(sys->arp_receive_fd > 0) + if (sys->arp_receive_fd > 0) close(sys->arp_receive_fd); - if(sys->sig_pipe_r > 0) + if (sys->sig_pipe_r > 0) close(sys->sig_pipe_r); - if(sys->sig_pipe_w > 0) - close(sys->sig_pipe_w); - - if(sys->epoll_fd) + if (sys->sig_pipe_w > 0) + close(sys->sig_pipe_w); + + if (sys->epoll_fd) close(sys->epoll_fd); - + free(sys); ICCPD_LOG_INFO(__FUNCTION__, "System resource pool destructed successfully..."); } @@ -146,53 +147,53 @@ struct CSM* system_create_csm() { struct System* sys = NULL; struct CSM* csm = NULL; - + if ((sys = system_get_instance()) == NULL ) - return NULL ; - + return NULL; + /* Create a new csm */ - csm = (struct CSM*) malloc(sizeof(struct CSM)); + csm = (struct CSM*)malloc(sizeof(struct CSM)); if (csm == NULL ) return NULL; else memset(csm, 0, sizeof(struct CSM)); iccp_csm_init(csm); LIST_INSERT_HEAD(&(sys->csm_list), csm, next); - + return csm; } /* Get connect state machine instance by peer ip */ -struct CSM* system_get_csm_by_peer_ip(const char* peer_ip) +struct CSM* system_get_csm_by_peer_ip(const char* peer_ip) { struct System* sys = NULL; struct CSM* csm = NULL; - + if ((sys = system_get_instance()) == NULL ) - return NULL ; - + return NULL; + LIST_FOREACH(csm, &(sys->csm_list), next) { if (strcmp(csm->peer_ip, peer_ip) == 0) return csm; } - - return NULL ; + + return NULL; } -struct CSM* system_get_csm_by_mlacp_id(int id) +struct CSM* system_get_csm_by_mlacp_id(int id) { struct System* sys = NULL; struct CSM* csm = NULL; - + if ((sys = system_get_instance()) == NULL ) - return NULL ; - + return NULL; + LIST_FOREACH(csm, &(sys->csm_list), next) { if (csm->app_csm.mlacp.id == id) return csm; } - - return NULL ; + + return NULL; } From de6ecb7c18756f75fa827ebc7976ea49b2e1cc60 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Mon, 29 Jul 2019 20:30:15 -0700 Subject: [PATCH 10/23] fix some bugs and make peer-link configuration optional Signed-off-by: shine.chen --- dockers/docker-iccpd/iccpd.j2 | 2 + src/iccpd/include/iccp_csm.h | 3 - src/iccpd/src/iccp_cli.c | 15 +++-- src/iccpd/src/iccp_csm.c | 8 +-- src/iccpd/src/iccp_netlink.c | 5 +- src/iccpd/src/mlacp_fsm.c | 25 ++++--- src/iccpd/src/mlacp_link_handler.c | 101 ++++++++++++++++++++++------- src/iccpd/src/mlacp_sync_prepare.c | 24 +++---- src/iccpd/src/mlacp_sync_update.c | 101 ++++++++++++++++++++++------- src/iccpd/src/port.c | 8 +++ src/iccpd/src/scheduler.c | 20 ++++-- 11 files changed, 211 insertions(+), 101 deletions(-) diff --git a/dockers/docker-iccpd/iccpd.j2 b/dockers/docker-iccpd/iccpd.j2 index f5446eb6f54a..be68ff127935 100644 --- a/dockers/docker-iccpd/iccpd.j2 +++ b/dockers/docker-iccpd/iccpd.j2 @@ -2,7 +2,9 @@ mclag_id:{{mclag_id}} local_ip:{{MC_LAG[mclag_id]['local_ip']}} peer_ip:{{MC_LAG[mclag_id]['peer_ip']}} +{% if MCLAG[mclag_id].has_key('peer_link') %} peer_link:{{MC_LAG[mclag_id]['peer_link']}} +{% endif %} mclag_interface:{{MC_LAG[mclag_id]['mclag_interface']}} {% endfor %} system_mac:{{DEVICE_METADATA['localhost']['mac']}} diff --git a/src/iccpd/include/iccp_csm.h b/src/iccpd/include/iccp_csm.h index 96a538bf2bb1..33db3717be24 100644 --- a/src/iccpd/include/iccp_csm.h +++ b/src/iccpd/include/iccp_csm.h @@ -116,9 +116,6 @@ struct CSM /* Msg queue */ TAILQ_HEAD(msg_list, Msg) msg_list; - /* System ID */ - time_t isolate_update_time; - /* STP role */ stp_role_type_et role_type; diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c index 6c020a2a500a..c4473bc7033e 100644 --- a/src/iccpd/src/iccp_cli.c +++ b/src/iccpd/src/iccp_cli.c @@ -98,6 +98,7 @@ int set_peer_link(int mid, const char* ifname) ICCPD_LOG_INFO(__FUNCTION__, "Change peer-link : %s -> %s", csm->peer_itf_name, ifname); + /*disconnect the link for mac and arp sync up before change peer_itf_name*/ scheduler_session_disconnect_handler(csm); if (csm->peer_link_if) @@ -120,6 +121,7 @@ int set_peer_link(int mid, const char* ifname) lif = local_if_find_by_name(csm->peer_itf_name); if (lif) { + /*When set peer-link, the local-if is already created*/ csm->peer_link_if = lif; lif->is_peer_link = 1; MLACP(csm).system_config_changed = 1; @@ -128,6 +130,9 @@ int set_peer_link(int mid, const char* ifname) iccp_get_port_member_list(lif); } + /*disconnect the link for mac and arp sync up*/ + scheduler_session_disconnect_handler(csm); + return 0; } @@ -142,12 +147,10 @@ int unset_peer_link(int mid) if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /*must be enabled mac learn*/ - set_peerlink_mlag_port_learn(csm->peer_link_if, 1); + if (csm->peer_link_if) + set_peerlink_mlag_port_learn(csm->peer_link_if, 1); } - /* Clean all port block*/ - peerlink_port_isolate_cleanup(csm); - /* update peer-link link handler*/ scheduler_session_disconnect_handler(csm); @@ -384,6 +387,8 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) The mac address separators could be either ':' or '-'*/ int parseMacString(const char * str_mac, uint8_t* bin_mac) { + int i; + if (bin_mac == NULL) { return -1; @@ -411,7 +416,7 @@ int parseMacString(const char * str_mac, uint8_t* bin_mac) return -1; } - for (int i = 0; i < ETHER_ADDR_LEN; ++i) + for (i = 0; i < ETHER_ADDR_LEN; ++i) { int left = i * 3; /* left digit position of hexadecimal number*/ int right = left + 1; /* right digit position of hexadecimal number*/ diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c index 2c9f9af3a083..09725e10ac86 100644 --- a/src/iccpd/src/iccp_csm.c +++ b/src/iccpd/src/iccp_csm.c @@ -140,8 +140,6 @@ void iccp_csm_status_reset(struct CSM* csm, int all) csm->heartbeat_send_time = 0; csm->heartbeat_update_time = 0; csm->peer_warm_reboot_time = 0; - /*csm->sysid_update_time = 0;*/ - csm->isolate_update_time = 0; csm->role_type = STP_ROLE_NONE; csm->sock_read_event_ptr = NULL; csm->peer_link_if = NULL; @@ -176,11 +174,9 @@ void iccp_csm_finalize(struct CSM* csm) /*If warm reboot, don't change port block and peer link MAC learning*/ if (sys->warmboot_exit != WARM_REBOOT) { - /* Clean all port block*/ - peerlink_port_isolate_cleanup(csm); - /*Enable peer link port MAC learning*/ - set_peerlink_mlag_port_learn(csm->peer_link_if, 1); + if (csm->peer_link_if) + set_peerlink_mlag_port_learn(csm->peer_link_if, 1); } /* Disconnect from peer */ diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c index 23e72c065f24..1dbd58cc38e1 100644 --- a/src/iccpd/src/iccp_netlink.c +++ b/src/iccpd/src/iccp_netlink.c @@ -241,7 +241,6 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) { /* portchannel member changed, update port isolate attribute*/ update_peerlink_isolate_from_all_csm_lif(csm); - csm->isolate_update_time = time(NULL); } } } @@ -325,13 +324,14 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) { memset(local_if->portchannel_member_buf, 0, 512); memcpy(local_if->portchannel_member_buf, temp_buf, sizeof(local_if->portchannel_member_buf) - 1); - + #if 0 if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { /*peerlink portchannel member changed*/ update_peerlink_isolate_from_all_csm_lif(csm); csm->isolate_update_time = time(NULL); } + #endif } } } @@ -738,7 +738,6 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) { lif = local_if_create(ifindex, ifname, if_whitelist[i].type); - lif->state = PORT_STATE_DOWN; if (IF_OPER_UP == op_state ) diff --git a/src/iccpd/src/mlacp_fsm.c b/src/iccpd/src/mlacp_fsm.c index 4ca90a5ccda2..8577e431accb 100644 --- a/src/iccpd/src/mlacp_fsm.c +++ b/src/iccpd/src/mlacp_fsm.c @@ -274,9 +274,12 @@ static void mlacp_sync_send_syncPeerLinkInfo(struct CSM* csm) if ((sys = system_get_instance()) == NULL) return; - memset(g_csm_buf, 0, CSM_BUFFER_SIZE); - msg_len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); - iccp_csm_send(csm, g_csm_buf, msg_len); + if (csm->peer_link_if) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + msg_len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); + iccp_csm_send(csm, g_csm_buf, msg_len); + } return; } @@ -567,13 +570,6 @@ void mlacp_fsm_transit(struct CSM* csm) return; } - /*Update port isolate after 3 seconds*/ - if (csm->isolate_update_time != 0 && (time(NULL) - csm->isolate_update_time) >= 3) - { - /*update_peerlink_isolate_from_all_csm_lif(csm);*/ - csm->isolate_update_time = 0; - } - mlacp_sync_send_heartbeat(csm); /* Dequeue msg if any*/ @@ -1105,9 +1101,12 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) len = mlacp_prepare_for_sys_config(csm, g_csm_buf, CSM_BUFFER_SIZE); iccp_csm_send(csm, g_csm_buf, len); - memset(g_csm_buf, 0, CSM_BUFFER_SIZE); - len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); - iccp_csm_send(csm, g_csm_buf, len); + if (csm->peer_link_if) + { + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + len = mlacp_prepare_for_port_peerlink_info(csm, g_csm_buf, CSM_BUFFER_SIZE, csm->peer_link_if); + iccp_csm_send(csm, g_csm_buf, len); + } MLACP(csm).system_config_changed = 0; } diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index 45d442a48a97..cfb8664e0831 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -615,16 +615,20 @@ static void set_peerlink_mlag_port_isolate( struct LocalInterface *lif, int enable) { - if (!csm || !csm->peer_link_if || !lif) + if (!lif) return; - if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + lif->isolate_to_peer_link = enable; + + if (!csm || !csm->peer_link_if ) return; - lif->isolate_to_peer_link = enable; + if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE) + return; + ICCPD_LOG_DEBUG(__FUNCTION__, "%s port-isolate from %s to %s", + enable ? "Enable" : "Disable", csm->peer_link_if->name, lif->name); update_peerlink_isolate_from_all_csm_lif(csm); - csm->isolate_update_time = time(NULL); /* Kernel also needs to block traffic from peerlink to mlag-port*/ set_peerlink_mlag_port_kernel_forward(csm, lif, enable); @@ -1130,7 +1134,6 @@ static void update_l2_mac_state(struct CSM *csm, /*portchannel down*/ if (po_state == 0) { - #if 1 mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down,flag %d del MAC: %s, MAC %s vlan-id %d", @@ -1152,21 +1155,41 @@ static void update_l2_mac_state(struct CSM *csm, } else { - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, flag %d redirect MAC to peer-link: %s, MAC %s vlan-id %d", - mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); - /*If local is aged but peer is not aged, redirect the mac to peer-link*/ - memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + if (strlen(csm->peer_itf_name) != 0) + { + /*Send mac add message to mclagsyncd. fdb_type is not changed*/ + /*Is need to delete the old item before add?(Old item probably is static)*/ + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) + { + memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + else + { + /*must redirect but peerlink is down, del mac from ASIC*/ + /*if peerlink change to up, mac will add back to ASIC*/ + del_mac_from_chip(mac_msg); + memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + } + + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, flag %d, redirect MAC to peer-link: %s, MAC %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + } + else + { + /*peer-link is not configured, del mac from ASIC, mac still in mac_list*/ + del_mac_from_chip(mac_msg); - /*Send mac add message to mclagsyncd. fdb_type is not changed*/ - /*Is need to delete the old item before add?(Old item probably is static)*/ - if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) - add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, flag %d, peer-link is not configured: %s, MAC %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + } } - #endif } else /*portchannel up*/ { + /*the old item is redirect to peerlink for portchannel down*/ + /*when this portchannel up, recover the mac back*/ if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "Intf up, redirect MAC to portchannel: %s, MAC %s vlan-id %d", @@ -1178,6 +1201,19 @@ static void update_l2_mac_state(struct CSM *csm, /*Reverse interface from peer-link to the original portchannel*/ memcpy(mac_msg->ifname, mac_msg->origin_ifname, MAX_L_PORT_NAME); + /*Send dynamic or static mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, mac_msg->fdb_type); + } + else + { + /*this may be peerlink is not configured and portchannel is down*/ + /*when this portchannel up, add the mac back to ASIC*/ + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf up, add MAC to ASIC: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + + /*Remove MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 0); + /*Send dynamic or static mac add message to mclagsyncd*/ add_mac_to_chip(mac_msg, mac_msg->fdb_type); } @@ -1257,7 +1293,10 @@ void mlacp_peer_conn_handler(struct CSM* csm) if ((sys = system_get_instance()) == NULL) return; - set_peerlink_mlag_port_learn(csm->peer_link_if, 0); + if (csm->peer_link_if) + { + set_peerlink_mlag_port_learn(csm->peer_link_if, 0); + } /*If peer connect again, don't flush FDB*/ if (first_time == 0) @@ -1351,7 +1390,7 @@ void mlacp_peer_disconn_handler(struct CSM* csm) ICCPD_LOG_DEBUG(__FUNCTION__, "Peer disconnect, del MAC for peer-link: %s, MAC %s vlan-id %d", mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); - /*Send mac del message to mclagsyncd*/ + /*Send mac del message to mclagsyncd, may be already deleted*/ del_mac_from_chip(mac_msg); TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); @@ -1359,6 +1398,9 @@ void mlacp_peer_disconn_handler(struct CSM* csm) free(msg); } + /* Clean all port block*/ + peerlink_port_isolate_cleanup(csm); + memcpy(MLACP(csm).remote_system.system_id, null_mac, ETHER_ADDR_LEN); /*If peer is disconnected, recover the MAC address.*/ @@ -1738,6 +1780,7 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint /*same MAC exist*/ if (mac_exist) { + /*orphan port mac or origin from_mclag_intf but state is down*/ if (strcmp(mac_info->ifname, csm->peer_itf_name) == 0) { /*Set MAC_AGE_LOCAL flag*/ @@ -1773,7 +1816,7 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d", mac_info->ifname, mac_info->mac_str, mac_info->vid); - /*If local and peer both aged, del the mac*/ + /*If local and peer both aged, del the mac (local orphan mac is here)*/ TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); free(msg->buf); free(msg); @@ -1783,18 +1826,30 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d, peer is not age, add back to chip", mac_info->ifname, mac_info->mac_str, mac_info->vid); + mac_info->fdb_type = MAC_TYPE_DYNAMIC; + if (from_mclag_intf && lif_po && lif_po->state == PORT_STATE_DOWN) { /*If local if is down, redirect the mac to peer-link*/ - memcpy(&mac_info->ifname, csm->peer_itf_name, IFNAMSIZ); - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link", - mac_info->ifname, mac_info->mac_str, mac_info->vid); + if (strlen(csm->peer_itf_name) != 0) + { + memcpy(&mac_info->ifname, csm->peer_itf_name, IFNAMSIZ); + + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) + { + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link", + mac_info->ifname, mac_info->mac_str, mac_info->vid); + } + } + + return; } /*If local is aged but peer is not aged, Send mac add message to mclagsyncd*/ - mac_info->fdb_type = MAC_TYPE_DYNAMIC; - - add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); + /*it is from_mclag_intf and port state is up, local orphan mac can not be here*/ + if (mac_lif->state == PORT_STATE_UP) + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); } } } diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c index 89b5be6caa17..03c3eabfb984 100644 --- a/src/iccpd/src/mlacp_sync_prepare.c +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -308,9 +308,9 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu memset(buf, 0, max_buf_size); icc_hdr = (ICCHdr*)buf; mlacp_fill_icc_header(csm, icc_hdr, msg_len); - - /* Prepare for ARP information TLV */ - tlv = (struct mLACPMACInfoTLV*)malloc(tlv_len); + + /* Prepare for MAC information TLV */ + tlv = (struct mLACPMACInfoTLV*) &buf[sizeof(ICCHdr)]; memset(tlv, 0, tlv_len); tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; @@ -320,11 +320,7 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu sprintf(tlv->mac_str, "%s", mac_msg->mac_str); sprintf(tlv->ifname, "%s", mac_msg->origin_ifname); tlv->vid = htons(mac_msg->vid); - - /* Fill MAC Information TLV */ - memcpy(&buf[sizeof(ICCHdr)], tlv, tlv_len); - free(tlv); - + #if 1 ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg type = TLV_T_MLACP_MAC_INFO"); ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s mac = %s, vid = %d, type = %d", mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); @@ -360,7 +356,7 @@ int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, mlacp_fill_icc_header(csm, icc_hdr, msg_len); /* Prepare for ARP information TLV */ - tlv = (struct mLACPARPInfoTLV*)malloc(tlv_len); + tlv = (struct mLACPARPInfoTLV*) &buf[sizeof(ICCHdr)]; memset(tlv, 0, tlv_len); tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; @@ -370,11 +366,7 @@ int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, sprintf(tlv->ifname, "%s", arp_msg->ifname); tlv->ipv4_addr = htonl(arp_msg->ipv4_addr); memcpy(tlv->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); - - /* Fill ARP Information TLV */ - memcpy(&buf[sizeof(ICCHdr)], tlv, tlv_len); - free(tlv); - + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s msg ifname %s mac =%02x:%02x:%02x:%02x:%02x:%02x ", tlv->ifname, arp_msg->ifname, tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); ICCPD_LOG_DEBUG(__FUNCTION__, " IP Addr = %s ", show_ip_str( tlv->ipv4_addr)); @@ -415,7 +407,7 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, if (vlan_id != NULL) num_of_vlan_id++; - tlv_len = sizeof(struct mLACPPortChannelInfoTLV) + sizeof(struct VLAN_ID) * num_of_vlan_id; + tlv_len = sizeof(struct mLACPPortChannelInfoTLV) + sizeof(struct mLACPVLANData) * num_of_vlan_id; if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) return -1; @@ -433,7 +425,7 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, tlv->icc_parameter.u_bit = 0; tlv->icc_parameter.f_bit = 0; tlv->icc_parameter.type = htons(TLV_T_MLACP_PORT_CHANNEL_INFO); - tlv->icc_parameter.len = htons(sizeof(struct mLACPPortChannelInfoTLV) - sizeof(ICCParameter) + sizeof(struct VLAN_ID) * num_of_vlan_id); + tlv->icc_parameter.len = htons(sizeof(struct mLACPPortChannelInfoTLV) - sizeof(ICCParameter) + sizeof(struct mLACPVLANData) * num_of_vlan_id); tlv->agg_id = htons(port_channel->po_id); tlv->ipv4_addr = htonl(port_channel->ipv4_addr); tlv->l3_mode = port_channel->l3_mode; diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c index 143dc45bf121..11320f97d1a7 100644 --- a/src/iccpd/src/mlacp_sync_update.c +++ b/src/iccpd/src/mlacp_sync_update.c @@ -184,21 +184,12 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* } } - if (!local_if) - { - if (!(local_if = local_if_find_by_name(tlv->ifname))) - { - /*If the interface is not exist, return*/ - return -255; - } - } - /* update MAC list*/ TAILQ_FOREACH(msg, &(MLACP(csm).mac_list), tail) { mac_msg = (struct MACMsg*)msg->buf; - /*Same MAC is exist in local switch*/ + /*Same MAC is exist in local switch, this may be mac move*/ if (strcmp(mac_msg->mac_str, tlv->mac_str) == 0 && mac_msg->vid == ntohs(tlv->vid)) { if (tlv->type == MAC_SYNC_ADD) @@ -214,20 +205,59 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* if (mac_msg->fdb_type != MAC_TYPE_STATIC) { /*Update local item*/ - memcpy(&mac_msg->ifname, tlv->ifname, MAX_L_PORT_NAME); memcpy(&mac_msg->origin_ifname, tlv->ifname, MAX_L_PORT_NAME); } /*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/ if (from_mclag_intf == 0 || (local_if->state == PORT_STATE_DOWN && strcmp(mac_msg->ifname, csm->peer_itf_name) != 0)) { - /*Redirect the mac to peer-link*/ - memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); - /*Set MAC_AGE_LOCAL flag*/ mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); - /*Send mac add message to mclagsyncd*/ + if (strlen(csm->peer_itf_name) != 0) + { + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) + { + /*Redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + + /*Send mac add message to mclagsyncd*/ + add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + } + else + { + /*must redirect but peerlink is down, del mac from ASIC*/ + /*if peerlink change to up, mac will add back to ASIC*/ + del_mac_from_chip(mac_msg); + + /*Redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + } + } + else + { + /*must redirect but no peerlink, del mac from ASIC*/ + del_mac_from_chip(mac_msg); + + /*Update local item*/ + memcpy(&mac_msg->ifname, tlv->ifname, MAX_L_PORT_NAME); + + /*if orphan port mac but no peerlink, don't keep this mac*/ + if (from_mclag_intf == 0) + { + TAILQ_REMOVE(&(MLACP(csm).mac_list), msg, tail); + free(msg->buf); + free(msg); + return 0; + } + } + } + else + { + /*Update local item*/ + memcpy(&mac_msg->ifname, tlv->ifname, MAX_L_PORT_NAME); + + /*from MCLAG port and the local port is up, add mac to ASIC to update port*/ add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); } } @@ -243,6 +273,7 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* } #endif } + #if 0 else if (tlv->type == MAC_SYNC_ACK) { /*Clean the MAC_AGE_PEER flag*/ @@ -250,6 +281,7 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ACK, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); } + #endif break; } @@ -290,13 +322,26 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* /*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/ if (from_mclag_intf == 0 || local_if->state == PORT_STATE_DOWN) { - /*Redirect the mac to peer-link*/ - memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); - /*Set MAC_AGE_LOCAL flag*/ mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); - ICCPD_LOG_DEBUG(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, add %s vlan-id %d, op_type %d", - mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + + if (strlen(csm->peer_itf_name) == 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "orphan port or portchannel is down, but peer-link is not configured: ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + + /*if orphan port mac but no peerlink, don't keep this mac*/ + if (from_mclag_intf == 0) + return 0; + } + else + { + /*Redirect the mac to peer-link*/ + memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, add %s vlan-id %d, op_type %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + } } if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) @@ -304,7 +349,7 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); /*ICCPD_LOG_INFO(__FUNCTION__, "add mac queue successfully");*/ - /*If the port is peerlink, it must be up*/ + /*If the mac is from orphan port, or from MCLAG port but the local port is down*/ if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) { /*Send mac add message to mclagsyncd*/ @@ -313,6 +358,7 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* } else { + /*from MCLAG port and the local port is up*/ add_mac_to_chip(mac_msg, mac_msg->fdb_type); } @@ -391,7 +437,7 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) { peer_link_if = local_if_find_by_name(csm->peer_itf_name); - if (!local_if_is_l3_mode(peer_link_if)) + if (peer_link_if && !local_if_is_l3_mode(peer_link_if)) { /* Is peer-linlk itf belong to a vlan the same as peer?*/ LIST_FOREACH(vlan_id_list, &(peer_link_if->vlan_list), port_next) @@ -620,13 +666,18 @@ int mlacp_fsm_update_peerlink_info(struct CSM* csm, { if (csm == NULL || tlv == NULL ) return -1; - ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port info from peer"); + + if (!csm->peer_link_if) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port info from peer, local peerlink is not exist!"); + return 0; + } if (csm->peer_link_if->type != tlv->port_type) - ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port type of peer %d is not same as local %d !", tlv->port_type, csm->peer_link_if->type); + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port type of peer %d is not same with local %d !", tlv->port_type, csm->peer_link_if->type); if (tlv->port_type == IF_T_VXLAN && strncmp(csm->peer_itf_name, tlv->if_name, strlen(csm->peer_itf_name))) - ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port is vxlan port and peerlink port at peer %s is not same as local peerlink port %s !", tlv->if_name, csm->peer_itf_name); + ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port is vxlan port and peerlink port at peer %s is not same with local peerlink port %s !", tlv->if_name, csm->peer_itf_name); return 0; } diff --git a/src/iccpd/src/port.c b/src/iccpd/src/port.c index 63791314dacf..64492d2a5e1b 100644 --- a/src/iccpd/src/port.c +++ b/src/iccpd/src/port.c @@ -364,6 +364,14 @@ void local_if_destroy(char *ifname) else local_if_remove(lif); + if (csm->peer_link_if && strcmp(csm->peer_link_if->name, ifname) == 0) + { + /*if the peerlink interface is not created, peer connection can not establish*/ + scheduler_session_disconnect_handler(csm); + csm->peer_link_if->is_peer_link = 0; + csm->peer_link_if = NULL; + } + csm = lif->csm; if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) goto to_mlacp_purge; diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c index 6ef15f17014c..256351b9e062 100644 --- a/src/iccpd/src/scheduler.c +++ b/src/iccpd/src/scheduler.c @@ -683,22 +683,28 @@ int scheduler_check_csm_config(struct CSM* csm) if (csm->mlag_id <= 0) ret = -1; - else if (strlen(csm->peer_itf_name) <= 0) - ret = -1; else if (strlen(csm->peer_ip) <= 0) ret = -1; else if (strlen(csm->sender_ip) <= 0) ret = -1; - else if ((lif = local_if_find_by_name(csm->peer_itf_name)) == NULL) - ret = -1; - else + else if (strlen(csm->peer_itf_name) != 0) { - lif->is_peer_link = 1; - csm->peer_link_if = lif; + lif = local_if_find_by_name(csm->peer_itf_name); + if (lif == NULL) + { + /*if peer-link is configured but the interface is not created, peer connection can not establish*/ + return -1; + } + else + { + lif->is_peer_link = 1; + csm->peer_link_if = lif; + } } if (ret == -1) ICCPD_LOG_INFO(__FUNCTION__, "mclag config is not complete or conflicting, please check!"); + /* Decide STP role*/ iccp_csm_stp_role_count(csm); From d2130aa83a27e2880b5d4cae1785ac2154bbc335 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Wed, 31 Jul 2019 00:26:24 -0700 Subject: [PATCH 11/23] refactor code per Brcm review Signed-off-by: shine.chen --- src/iccpd/include/mlacp_tlv.h | 3 --- src/iccpd/src/iccp_netlink.c | 1 - src/iccpd/src/mlacp_link_handler.c | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/iccpd/include/mlacp_tlv.h b/src/iccpd/include/mlacp_tlv.h index 947a491a3846..caf448288014 100644 --- a/src/iccpd/include/mlacp_tlv.h +++ b/src/iccpd/include/mlacp_tlv.h @@ -136,7 +136,6 @@ struct mLACPPortConfigTLV char port_name[MAX_L_PORT_NAME]; /* NOS */ - uint8_t orphan; uint8_t l3_mode; } __attribute__ ((packed)); @@ -205,7 +204,6 @@ struct mLACPPortStateTLV uint16_t agg_id; /* NOS */ - uint8_t orphan; uint16_t port_id; uint8_t l3_mode; uint8_t is_peer_link; @@ -321,7 +319,6 @@ struct mLACPPortChannelInfoTLV uint8_t if_name_len; uint8_t l3_mode; uint32_t ipv4_addr; - uint16_t orphan; uint16_t po_id; uint16_t num_of_vlan_id; struct mLACPVLANData vlanData[0]; diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c index 1dbd58cc38e1..36739b2665e5 100644 --- a/src/iccpd/src/iccp_netlink.c +++ b/src/iccpd/src/iccp_netlink.c @@ -329,7 +329,6 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg) { /*peerlink portchannel member changed*/ update_peerlink_isolate_from_all_csm_lif(csm); - csm->isolate_update_time = time(NULL); } #endif } diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index cfb8664e0831..fddb252436b0 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -1837,7 +1837,7 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) { - add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); + add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link", mac_info->ifname, mac_info->mac_str, mac_info->vid); } From 7b89a0695c8472da68ee04b95854669f951a8a98 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Wed, 14 Aug 2019 19:25:24 -0700 Subject: [PATCH 12/23] correct a typo Signed-off-by: shine.chen --- dockers/docker-iccpd/iccpd.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dockers/docker-iccpd/iccpd.j2 b/dockers/docker-iccpd/iccpd.j2 index be68ff127935..6c6f9fab1afa 100644 --- a/dockers/docker-iccpd/iccpd.j2 +++ b/dockers/docker-iccpd/iccpd.j2 @@ -2,7 +2,7 @@ mclag_id:{{mclag_id}} local_ip:{{MC_LAG[mclag_id]['local_ip']}} peer_ip:{{MC_LAG[mclag_id]['peer_ip']}} -{% if MCLAG[mclag_id].has_key('peer_link') %} +{% if MC_LAG[mclag_id].has_key('peer_link') %} peer_link:{{MC_LAG[mclag_id]['peer_link']}} {% endif %} mclag_interface:{{MC_LAG[mclag_id]['mclag_interface']}} From db3cc0b7512bab0c9188d261d04b0116377542f9 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Wed, 14 Aug 2019 19:37:58 -0700 Subject: [PATCH 13/23] * optimize iccpd arp/mac sync process * refine code according to brcm opinoin * unify function return value Signed-off-by: shine.chen --- src/iccpd/include/mlacp_sync_prepare.h | 4 +- src/iccpd/include/mlacp_tlv.h | 42 ++++--- src/iccpd/include/port.h | 1 + src/iccpd/include/system.h | 2 + src/iccpd/src/app_csm.c | 6 +- src/iccpd/src/iccp_cli.c | 50 ++++---- src/iccpd/src/iccp_cmd.c | 2 +- src/iccpd/src/iccp_cmd_show.c | 2 +- src/iccpd/src/iccp_csm.c | 8 +- src/iccpd/src/iccp_ifm.c | 9 +- src/iccpd/src/iccp_main.c | 4 +- src/iccpd/src/iccp_netlink.c | 18 +-- src/iccpd/src/mclagdctl/mclagdctl.c | 32 ++--- src/iccpd/src/mclagdctl/mclagdctl.h | 9 +- src/iccpd/src/mlacp_fsm.c | 46 +++++-- src/iccpd/src/mlacp_link_handler.c | 132 +++++++++---------- src/iccpd/src/mlacp_sync_prepare.c | 168 +++++++++++++------------ src/iccpd/src/mlacp_sync_update.c | 144 ++++++++++++--------- src/iccpd/src/port.c | 10 +- src/iccpd/src/scheduler.c | 34 ++--- 20 files changed, 394 insertions(+), 329 deletions(-) diff --git a/src/iccpd/include/mlacp_sync_prepare.h b/src/iccpd/include/mlacp_sync_prepare.h index ec480be324dc..f4ea7a419f51 100644 --- a/src/iccpd/include/mlacp_sync_prepare.h +++ b/src/iccpd/include/mlacp_sync_prepare.h @@ -44,8 +44,8 @@ int mlacp_sync_with_kernel_callback(); int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_buf_size); int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end); int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size); -int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg); -int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg); +int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg, int count); +int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count); int mlacp_prepare_for_heartbeat(struct CSM* csm, char* buf, size_t max_buf_size); int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* local_if); int mlacp_prepare_for_Aggport_config(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* lif, int purge_flag); diff --git a/src/iccpd/include/mlacp_tlv.h b/src/iccpd/include/mlacp_tlv.h index caf448288014..86bce2e0e943 100644 --- a/src/iccpd/include/mlacp_tlv.h +++ b/src/iccpd/include/mlacp_tlv.h @@ -346,19 +346,34 @@ struct mLACPVLANInfoTLV struct mLACPVLANData vlanData[0]; } __attribute__ ((packed)); +/* Mac entry Information TLV*/ +struct mLACPMACData +{ + uint8_t type;/*add or del*/ + char mac_str[ETHER_ADDR_STR_LEN]; + uint16_t vid; + /*Current if name that set in chip*/ + char ifname[MAX_L_PORT_NAME]; +} __attribute__ ((packed)); + /* * MAC Information TLV */ struct mLACPMACInfoTLV { ICCParameter icc_parameter; - uint8_t type;/*add or del*/ - char mac_str[32]; - uint16_t vid; - /*Current if name that set in chip*/ - char ifname[MAX_L_PORT_NAME]; + uint16_t num_of_entry; + struct mLACPMACData MacEntry[0]; } __attribute__ ((packed)); +struct ARPMsg +{ + uint8_t op_type; + char ifname[MAX_L_PORT_NAME]; + uint32_t ipv4_addr; + uint8_t mac_addr[ETHER_ADDR_LEN]; +}; + /* * ARP Information TLV */ @@ -366,10 +381,8 @@ struct mLACPARPInfoTLV { ICCParameter icc_parameter; /* Local Interface ID */ - uint8_t type; - char ifname[MAX_L_PORT_NAME]; - uint32_t ipv4_addr; - uint8_t mac_addr[ETHER_ADDR_LEN]; + uint16_t num_of_entry; + struct ARPMsg ArpEntry[0]; } __attribute__ ((packed)); /* @@ -407,15 +420,6 @@ enum ARP_OP_TYPE ARP_SYNC_DEL, }; -struct ARPMsg -{ - uint8_t op_type; - char ifname[MAX_L_PORT_NAME]; - uint32_t ipv4_addr; - uint8_t mac_addr[ETHER_ADDR_LEN]; - time_t update_time; -}; - enum MAC_AGE_TYPE { MAC_AGE_LOCAL = 1, /*MAC in local switch is ageout*/ @@ -439,7 +443,7 @@ struct MACMsg { uint8_t op_type; /*add or del*/ uint8_t fdb_type; /*static or dynamic*/ - char mac_str[32]; + char mac_str[ETHER_ADDR_STR_LEN]; uint16_t vid; /*Current if name that set in chip*/ char ifname[MAX_L_PORT_NAME]; diff --git a/src/iccpd/include/port.h b/src/iccpd/include/port.h index 91bdc9966209..2da00fef10fe 100644 --- a/src/iccpd/include/port.h +++ b/src/iccpd/include/port.h @@ -29,6 +29,7 @@ #include #define ETHER_ADDR_LEN 6 +#define ETHER_ADDR_STR_LEN 18 /* * RFC 7275 * 7.2.4. mLACP Port Config TLV diff --git a/src/iccpd/include/system.h b/src/iccpd/include/system.h index 1205fe55f9ad..bb89dbb2f3c2 100644 --- a/src/iccpd/include/system.h +++ b/src/iccpd/include/system.h @@ -44,6 +44,8 @@ #define WARM_REBOOT 1 +#define MCLAG_ERROR -1 + struct CSM; #ifndef MAX_BUFSIZE diff --git a/src/iccpd/src/app_csm.c b/src/iccpd/src/app_csm.c index 7d8f8c550d89..6588587bd8ec 100644 --- a/src/iccpd/src/app_csm.c +++ b/src/iccpd/src/app_csm.c @@ -196,7 +196,7 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) struct LocalInterface* lif_po = NULL; if (csm == NULL || lif == NULL) - return -1; + return MCLAG_ERROR; if (lif->csm == csm) return 0; @@ -252,7 +252,7 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) ICCPD_LOG_WARN(__FUNCTION__, "Failed to find port_channel instance for %d.", lif->po_id); - return -1; + return MCLAG_ERROR; } lif_po->csm = csm; @@ -267,7 +267,7 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) int mlacp_unbind_local_if(struct LocalInterface* lif) { if (lif == NULL ) - return -1; + return MCLAG_ERROR; if (lif->csm == NULL ) return 0; diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c index c4473bc7033e..ba0995b50451 100644 --- a/src/iccpd/src/iccp_cli.c +++ b/src/iccpd/src/iccp_cli.c @@ -35,7 +35,7 @@ int set_mc_lag_id( struct CSM *csm, uint16_t id) { if (!csm) - return -1; + return MCLAG_ERROR; ICCPD_LOG_INFO(__FUNCTION__, "Set mlag-id : %d", id); @@ -50,7 +50,7 @@ int set_mc_lag_id( struct CSM *csm, uint16_t id) int unset_mc_lag_id( struct CSM *csm, uint16_t id) { if (!csm) - return -1; + return MCLAG_ERROR; /* Mlag-ID, RG-ID, MLACP-ID*/ csm->mlag_id = 0; @@ -76,15 +76,15 @@ int set_peer_link(int mid, const char* ifname) if (strncmp(ifname, FRONT_PANEL_PORT_PREFIX, strlen(FRONT_PANEL_PORT_PREFIX)) != 0 && strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0 && strncmp(ifname, VXLAN_TUNNEL_PREFIX, strlen(VXLAN_TUNNEL_PREFIX)) != 0) { ICCPD_LOG_ERR(__FUNCTION__, "Peer-link is %s, must be Ethernet or PortChannel or VTTNL(Vxlan tunnel)", ifname); - return -1; + return MCLAG_ERROR; } csm = system_get_csm_by_mlacp_id(mid); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (len > IFNAMSIZ) - return -1; + return MCLAG_ERROR; if (strlen(csm->peer_itf_name) > 0) { @@ -142,7 +142,7 @@ int unset_peer_link(int mid) csm = system_get_csm_by_mlacp_id(mid); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) { @@ -176,9 +176,9 @@ int set_local_address(int mid, const char* addr) csm = system_get_csm_by_mlacp_id(mid); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (addr == NULL) - return -1; + return MCLAG_ERROR; if (strlen(csm->sender_ip) > 0) { @@ -214,7 +214,7 @@ int unset_local_address(int mid) csm = system_get_csm_by_mlacp_id(mid); if (csm == NULL) - return -1; + return MCLAG_ERROR; memset(csm->sender_ip, 0, INET_ADDRSTRLEN); memset(csm->iccp_info.sender_name, 0, INET_ADDRSTRLEN); @@ -235,9 +235,9 @@ int set_peer_address(int mid, const char* addr) csm = system_get_csm_by_mlacp_id(mid); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (addr == NULL) - return -1; + return MCLAG_ERROR; len = strlen(addr); @@ -272,7 +272,7 @@ int unset_peer_address(int mid) csm = system_get_csm_by_mlacp_id(mid); if (csm == NULL) - return -1; + return MCLAG_ERROR; memset(csm->peer_ip, 0, INET_ADDRSTRLEN); @@ -289,20 +289,20 @@ int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname struct If_info * cif = NULL; if (!ifname) - return -1; + return MCLAG_ERROR; if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "attach interface(%s) is not a port-channel", ifname); - return -1; + return MCLAG_ERROR; } csm = system_get_csm_by_mlacp_id(domain); if (csm == NULL) { ICCPD_LOG_DEBUG(__FUNCTION__, "MC-LAG ID %d doesn't exist", domain); - return -1; + return MCLAG_ERROR; } lif = local_if_find_by_name(ifname); @@ -321,7 +321,7 @@ int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname { cif = (struct If_info *)malloc(sizeof(struct If_info)); if (!cif) - return -1; + return MCLAG_ERROR; snprintf(cif->name, MAX_L_PORT_NAME, "%s", ifname); LIST_INSERT_HEAD(&(csm->if_bind_list), cif, csm_next); @@ -339,13 +339,13 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) struct If_info * cif = NULL; if (!ifname) - return -1; + return MCLAG_ERROR; if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "detach interface(%s) is not a port-channel", ifname); - return -1; + return MCLAG_ERROR; } /* find po*/ @@ -354,7 +354,7 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) || lif_po->po_id <= 0 || lif_po->csm == NULL) { - return -1; + return MCLAG_ERROR; } /* find csm*/ @@ -391,13 +391,13 @@ int parseMacString(const char * str_mac, uint8_t* bin_mac) if (bin_mac == NULL) { - return -1; + return MCLAG_ERROR; } /* 6 hexadecimal numbers (two digits each) + 5 delimiters*/ if (strlen(str_mac) != ETHER_ADDR_LEN * 2 + 5) { - return -1; + return MCLAG_ERROR; } /* first check that all mac address separators are equal to each other @@ -407,13 +407,13 @@ int parseMacString(const char * str_mac, uint8_t* bin_mac) && str_mac[8] == str_mac[11] && str_mac[11] == str_mac[14])) { - return -1; + return MCLAG_ERROR; } /* then check that the first separator is equal to ':' or '-'*/ if (str_mac[2] != ':' && str_mac[2] != '-') { - return -1; + return MCLAG_ERROR; } for (i = 0; i < ETHER_ADDR_LEN; ++i) @@ -435,7 +435,7 @@ int parseMacString(const char * str_mac, uint8_t* bin_mac) } else { - return -1; + return MCLAG_ERROR; } bin_mac[i] = (uint8_t)(bin_mac[i] << 4); @@ -454,7 +454,7 @@ int parseMacString(const char * str_mac, uint8_t* bin_mac) } else { - return -1; + return MCLAG_ERROR; } } diff --git a/src/iccpd/src/iccp_cmd.c b/src/iccpd/src/iccp_cmd.c index fc9082bf042b..50025a8e3810 100644 --- a/src/iccpd/src/iccp_cmd.c +++ b/src/iccpd/src/iccp_cmd.c @@ -44,7 +44,7 @@ int set_mc_lag_by_id(uint16_t mid) csm = (struct CSM*)iccp_get_csm(); if (csm == NULL) { - return -1; + return MCLAG_ERROR; } ret = set_mc_lag_id(csm, mid); diff --git a/src/iccpd/src/iccp_cmd_show.c b/src/iccpd/src/iccp_cmd_show.c index 70aaaf98b6bf..ee01fe9a6629 100644 --- a/src/iccpd/src/iccp_cmd_show.c +++ b/src/iccpd/src/iccp_cmd_show.c @@ -241,7 +241,7 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id) mclagd_mac.op_type = iccpd_mac->op_type; mclagd_mac.fdb_type = iccpd_mac->fdb_type; - memcpy(mclagd_mac.mac_str, iccpd_mac->mac_str, 32); + memcpy(mclagd_mac.mac_str, iccpd_mac->mac_str, ETHER_ADDR_STR_LEN); mclagd_mac.vid = iccpd_mac->vid; memcpy(mclagd_mac.ifname, iccpd_mac->ifname, strlen(iccpd_mac->ifname)); memcpy(mclagd_mac.origin_ifname, iccpd_mac->origin_ifname, strlen(iccpd_mac->origin_ifname)); diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c index 09725e10ac86..c4da855b98a1 100644 --- a/src/iccpd/src/iccp_csm.c +++ b/src/iccpd/src/iccp_csm.c @@ -220,7 +220,7 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len) ICCParameter* param = NULL; if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0) - return -1; + return MCLAG_ERROR; if (ntohs(ldp_hdr->msg_type) == MSG_T_CAPABILITY) param = (struct ICCParameter*)&buf[sizeof(LDPHdr)]; @@ -373,7 +373,7 @@ int iccp_csm_prepare_iccp_msg(struct CSM* csm, char* buf, size_t max_buf_size) size_t msg_len = -1; if (csm == NULL || buf == NULL) - return -1; + return MCLAG_ERROR; switch (csm->current_state) { @@ -750,7 +750,7 @@ int iccp_csm_init_msg(struct Msg** msg, char* data, int len) return -2; if (data == NULL || len <= 0) - return -1; + return MCLAG_ERROR; iccp_msg = (struct Msg*)malloc(sizeof(struct Msg)); if (iccp_msg == NULL) @@ -774,7 +774,7 @@ int iccp_csm_init_msg(struct Msg** msg, char* data, int len) free(iccp_msg); } - return -1; + return MCLAG_ERROR; } void iccp_csm_stp_role_count(struct CSM *csm) diff --git a/src/iccpd/src/iccp_ifm.c b/src/iccpd/src/iccp_ifm.c index d97de7be938a..e8b33b58184a 100644 --- a/src/iccpd/src/iccp_ifm.c +++ b/src/iccpd/src/iccp_ifm.c @@ -71,7 +71,7 @@ int iccp_sys_local_if_list_get_init() int retry = 1; if (!(sys = system_get_instance())) - return -1; + return MCLAG_ERROR; while (retry) { @@ -245,7 +245,6 @@ static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } - time(&arp_info->update_time); } break; } @@ -372,7 +371,7 @@ int do_one_neigh_request(struct nlmsghdr *n) len -= NLMSG_LENGTH(sizeof(*ndm)); if (len < 0) - return -1; + return MCLAG_ERROR; ifm_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); @@ -421,7 +420,7 @@ int iccp_arp_get_init() int retry = 1; if (!(sys = system_get_instance())) - return -1; + return MCLAG_ERROR; while (retry) { @@ -572,8 +571,6 @@ void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETH ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } - time(&arp_info->update_time); - break; } diff --git a/src/iccpd/src/iccp_main.c b/src/iccpd/src/iccp_main.c index 0ca9c13211ed..86920f07e1fb 100644 --- a/src/iccpd/src/iccp_main.c +++ b/src/iccpd/src/iccp_main.c @@ -39,7 +39,7 @@ int check_instance(char* pid_file_path) int rc = 0; if (pid_file_path == NULL) - return -1; + return MCLAG_ERROR; pid_file = open(pid_file_path, O_CREAT | O_RDWR, 0666); if (pid_file <= 0 ) @@ -223,7 +223,7 @@ int main(int argc, char* argv[]) if (parser.parse(&parser, argc, argv) != 0) { parser.finalize(&parser); - return -1; + return MCLAG_ERROR; } pid_file_fd = check_instance(parser.pid_file_path); diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c index 36739b2665e5..59a17cd22e40 100644 --- a/src/iccpd/src/iccp_netlink.c +++ b/src/iccpd/src/iccp_netlink.c @@ -345,7 +345,7 @@ int iccp_genric_socket_team_family_get() int grp_id = 0; if ((sys = system_get_instance()) == NULL ) - return -1; + return MCLAG_ERROR; if (sys->family < 0) { sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME); @@ -423,7 +423,7 @@ int iccp_netlink_if_hwaddr_set(uint32_t ifindex, uint8_t *addr, unsigned int add struct System* sys = NULL; if (!(sys = system_get_instance())) - return -1; + return MCLAG_ERROR; link = rtnl_link_alloc(); if (!link) @@ -763,17 +763,17 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) { lif->state = PORT_STATE_UP; /*if(lif->type ==IF_T_PORT_CHANNEL)*/ - iccp_from_netlink_port_state_handler(lif->name, lif->state); + ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state up", ifname); - ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); + iccp_from_netlink_port_state_handler(lif->name, lif->state); } else if (lif->state == PORT_STATE_UP && ( IF_OPER_UP != op_state || !(link_flag & IFF_LOWER_UP))) { lif->state = PORT_STATE_DOWN; /*if(lif->type ==IF_T_PORT_CHANNEL)*/ - iccp_from_netlink_port_state_handler(lif->name, lif->state); + ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state down", ifname); - ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state %x ", ifname, op_state ); + iccp_from_netlink_port_state_handler(lif->name, lif->state); } switch (addr_type) @@ -874,7 +874,7 @@ int iccp_sys_local_if_list_get_addr() int retry = 1; if (!(sys = system_get_instance())) - return -1; + return MCLAG_ERROR; while (retry) { @@ -970,7 +970,7 @@ int iccp_system_init_netlink_socket() int err = 0; if ((sys = system_get_instance()) == NULL ) - return -1; + return MCLAG_ERROR; sys->genric_sock = nl_socket_alloc(); if (!sys->genric_sock) @@ -1225,7 +1225,7 @@ static int iccp_receive_arp_packet_handler(struct System *sys) if (n < 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "arp recvfrom: %s", buf); - return -1; + return MCLAG_ERROR; } /* Sanity checks */ diff --git a/src/iccpd/src/mclagdctl/mclagdctl.c b/src/iccpd/src/mclagdctl/mclagdctl.c index 6e6c1f1e2d75..bf0e6528d6bf 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.c +++ b/src/iccpd/src/mclagdctl/mclagdctl.c @@ -109,13 +109,13 @@ int mclagdctl_sock_connect() return 0; if (strlen(mclagdctl_sock_path) <= 0) - return -1; + return MCLAG_ERROR; mclagdctl_sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (mclagdctl_sock_fd < 0) { - return -1; + return MCLAG_ERROR; } memset(&addr, 0, sizeof(addr)); @@ -127,7 +127,7 @@ int mclagdctl_sock_connect() { close(mclagdctl_sock_fd); mclagdctl_sock_fd = -1; - return -1; + return MCLAG_ERROR; } return 0; @@ -178,22 +178,22 @@ int mclagdctl_sock_read(int fd, unsigned char *r_buf, int total_len) switch ((ret = select(fd + 1, &read_fd, NULL, NULL, &tv))) { - case -1: // error - fprintf(stdout, "Mclagdctl:Select return error:%s\n", strerror(errno)); - return -1; + case -1: // error + fprintf(stdout, "Mclagdctl:Select return error:%s\n", strerror(errno)); + return MCLAG_ERROR; - case 0: // timeout - fprintf(stdout, "Mclagdctl:Select timeout:%s\n", strerror(errno)); - return -1; + case 0: // timeout + fprintf(stdout, "Mclagdctl:Select timeout:%s\n", strerror(errno)); + return MCLAG_ERROR; - default: - break; + default: + break; } ret = read(fd, r_buf + read_len, total_len - read_len); if (ret <= 0) { - return -1; + return MCLAG_ERROR; } read_len += ret; } @@ -264,7 +264,7 @@ int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv) if (mclag_id <= 0) { fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); - return -1; + return MCLAG_ERROR; } memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); @@ -314,7 +314,7 @@ int mclagdctl_enca_dump_mac(char *msg, int mclag_id, int argc, char **argv) if (mclag_id <= 0) { fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); - return -1; + return MCLAG_ERROR; } memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); @@ -381,7 +381,7 @@ int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc, char * if (mclag_id <= 0) { fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); - return -1; + return MCLAG_ERROR; } memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); @@ -458,7 +458,7 @@ int mclagdctl_enca_dump_peer_portlist(char *msg, int mclag_id, int argc, char * if (mclag_id <= 0) { fprintf(stderr, "Need to specify mclag-id through the parameter i !\n"); - return -1; + return MCLAG_ERROR; } memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); diff --git a/src/iccpd/src/mclagdctl/mclagdctl.h b/src/iccpd/src/mclagdctl/mclagdctl.h index 7da8d0817218..049e301a66d6 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.h +++ b/src/iccpd/src/mclagdctl/mclagdctl.h @@ -27,6 +27,7 @@ #define MCLAGDCTL_INET_ADDR_LEN 32 #define MCLAGDCTL_ETHER_ADDR_LEN 6 #define MCLAGDCTL_PORT_MEMBER_BUF_LEN 512 +#define ETHER_ADDR_STR_LEN 18 typedef int (*call_enca_msg_fun)(char *msg, int mclag_id, int argc, char **argv); typedef int (*call_parse_msg_fun)(char *msg, int data_len); @@ -86,6 +87,8 @@ struct mclagd_reply_hdr #define EXEC_TYPE_NO_EXIST_MCLAGID -3 #define EXEC_TYPE_FAILED -4 +#define MCLAG_ERROR -1 + #define MCLAGD_REPLY_INFO_HDR (sizeof(struct mclagd_reply_hdr) + sizeof(int)) #define MCLAGDCTL_COMMAND_PARAM_MAX_CNT 8 @@ -122,9 +125,9 @@ struct mclagd_arp_msg struct mclagd_mac_msg { - unsigned char op_type; /*add or del*/ - unsigned char fdb_type; /*static or dynamic*/ - char mac_str[32]; + unsigned char op_type;/*add or del*/ + unsigned char fdb_type;/*static or dynamic*/ + char mac_str[ETHER_ADDR_STR_LEN]; unsigned short vid; /*Current if name that set in chip*/ char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; diff --git a/src/iccpd/src/mlacp_fsm.c b/src/iccpd/src/mlacp_fsm.c index 8577e431accb..d5c6f254945d 100644 --- a/src/iccpd/src/mlacp_fsm.c +++ b/src/iccpd/src/mlacp_fsm.c @@ -201,24 +201,36 @@ static void mlacp_sync_send_aggState(struct CSM* csm) return; } - +#define MAX_MAC_ENTRY_NUM 30 +#define MAX_ARP_ENTRY_NUM 40 static void mlacp_sync_send_syncMacInfo(struct CSM* csm) { int msg_len = 0; struct Msg* msg = NULL; + int count = 0; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); while (!TAILQ_EMPTY(&(MLACP(csm).mac_msg_list))) { msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list)); TAILQ_REMOVE(&(MLACP(csm).mac_msg_list), msg, tail); - memset(g_csm_buf, 0, CSM_BUFFER_SIZE); - msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct MACMsg*)msg->buf); - iccp_csm_send(csm, g_csm_buf, msg_len); + msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct MACMsg*)msg->buf, count); + count++; free(msg->buf); free(msg); + if (count >= MAX_MAC_ENTRY_NUM) + { + iccp_csm_send(csm, g_csm_buf, msg_len); + count = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + } /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] MacInfo,len=[%d]", msg_len);*/ } + if (count) + iccp_csm_send(csm, g_csm_buf, msg_len); + return; } @@ -226,19 +238,31 @@ static void mlacp_sync_send_syncArpInfo(struct CSM* csm) { int msg_len = 0; struct Msg* msg = NULL; + int count = 0; + + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); while (!TAILQ_EMPTY(&(MLACP(csm).arp_msg_list))) { msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list)); TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); - memset(g_csm_buf, 0, CSM_BUFFER_SIZE); - msg_len = mlacp_prepare_for_arp_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct ARPMsg*)msg->buf); - iccp_csm_send(csm, g_csm_buf, msg_len); + + msg_len = mlacp_prepare_for_arp_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct ARPMsg*)msg->buf, count); + count++; free(msg->buf); free(msg); + if (count >= MAX_ARP_ENTRY_NUM) + { + iccp_csm_send(csm, g_csm_buf, msg_len); + count = 0; + memset(g_csm_buf, 0, CSM_BUFFER_SIZE); + } /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] ArpInfo,len=[%d]", msg_len);*/ } + if (count) + iccp_csm_send(csm, g_csm_buf, msg_len); + return; } @@ -324,7 +348,7 @@ static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg) sysconf = (mLACPSysConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); - if (mlacp_fsm_update_system_conf(csm, sysconf) == -1) + if (mlacp_fsm_update_system_conf(csm, sysconf) == MCLAG_ERROR) { /*NOTE: we just change the node ID local side without sending NAK msg*/ ICCPD_LOG_DEBUG("mlacp_fsm", " Same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id); @@ -357,7 +381,7 @@ static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg) mLACPAggConfigTLV* portconf = NULL; portconf = (mLACPAggConfigTLV*)&(msg->buf[sizeof(ICCHdr)]); - if (mlacp_fsm_update_Agg_conf(csm, portconf) == -1) + if (mlacp_fsm_update_Agg_conf(csm, portconf) == MCLAG_ERROR) { mlacp_sync_send_nak_handler(csm, msg); } @@ -370,7 +394,7 @@ static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg) mLACPAggPortStateTLV* portstate = NULL; portstate = (mLACPAggPortStateTLV*)&(msg->buf[sizeof(ICCHdr)]); - if (mlacp_fsm_update_Aggport_state(csm, portstate) == -1) + if (mlacp_fsm_update_Aggport_state(csm, portstate) == MCLAG_ERROR) { mlacp_sync_send_nak_handler(csm, msg); /*MLACP(csm).error_msg = "Receive a port state update on an non-existed port. It is suggest to check the environment and re-initialize mLACP again.";*/ @@ -412,7 +436,7 @@ static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg) mLACPPortChannelInfoTLV* portconf = NULL; portconf = (mLACPPortChannelInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); - if (mlacp_fsm_update_port_channel_info(csm, portconf) == -1) + if (mlacp_fsm_update_port_channel_info(csm, portconf) == MCLAG_ERROR) { mlacp_sync_send_nak_handler(csm, msg); } diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index fddb252436b0..f7a25826b451 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -79,12 +79,12 @@ static int getHwAddr(char *buff, char *mac) if ( buff == NULL || mac == NULL ) { - return -1; + return MCLAG_ERROR; } if (sscanf(mac, "%x:%x:%x:%x:%x:%x", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]) < 6) { - return -1; + return MCLAG_ERROR; } for (i = 0; i < 6; i++) @@ -109,7 +109,7 @@ int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac) if (ifname == NULL || ip == 0 || mac == NULL) { - return -1; + return MCLAG_ERROR; } /*you must add this becasue some system will return "Invlid argument" @@ -123,7 +123,7 @@ int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac) if (getHwAddr((char *)arpreq.arp_ha.sa_data, mac) < 0) { - return -1; + return MCLAG_ERROR; } strncpy(arpreq.arp_dev, ifname, 15); @@ -135,14 +135,14 @@ int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac) sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if (sock_fd < 0) { - return -1; + return MCLAG_ERROR; } rc = ioctl(sock_fd, SIOCSARP, &arpreq); if (rc < 0) { close(sock_fd); - return -1; + return MCLAG_ERROR; } close(sock_fd); @@ -163,7 +163,7 @@ int mlacp_fsm_arp_del(char *ifname, uint32_t ip) if (ifname == NULL || ip == 0) { - return -1; + return MCLAG_ERROR; } /*you must add this becasue some system will return "Invlid argument" @@ -181,14 +181,14 @@ int mlacp_fsm_arp_del(char *ifname, uint32_t ip) sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if (sock_fd < 0) { - return -1; + return MCLAG_ERROR; } rc = ioctl(sock_fd, SIOCDARP, &arpreq); if (rc < 0) { close(sock_fd); - return -1; + return MCLAG_ERROR; } close(sock_fd); @@ -981,14 +981,14 @@ void update_stp_peer_link(struct CSM *csm, void iccp_get_fdb_change_from_syncd( void) { struct IccpSyncdHDr * msg_hdr; - char *msg_buf = g_csm_buf; + char msg_buf[512]; struct System *sys; sys = system_get_instance(); if (sys == NULL) return; - memset(msg_buf, 0, CSM_BUFFER_SIZE); + memset(msg_buf, 0, 512); msg_hdr = (struct IccpSyncdHDr *)msg_buf; msg_hdr->ver = 1; @@ -1008,7 +1008,7 @@ void iccp_get_fdb_change_from_syncd( void) void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg, uint8_t mac_type) { struct IccpSyncdHDr * msg_hdr; - char *msg_buf = g_csm_buf; + char msg_buf[512]; struct System *sys; struct mclag_fdb_info * mac_info; @@ -1016,7 +1016,7 @@ void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg, uint8_t mac_type) if (sys == NULL) return; - memset(msg_buf, 0, CSM_BUFFER_SIZE); + memset(msg_buf, 0, 512); msg_hdr = (struct IccpSyncdHDr *)msg_buf; msg_hdr->ver = 1; @@ -1026,7 +1026,7 @@ void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg, uint8_t mac_type) mac_info = (struct mclag_fdb_info *)&msg_buf[sizeof(struct IccpSyncdHDr)]; mac_info->vid = mac_msg->vid; memcpy(mac_info->port_name, mac_msg->ifname, MAX_L_PORT_NAME); - memcpy(mac_info->mac, mac_msg->mac_str, 32); + memcpy(mac_info->mac, mac_msg->mac_str, ETHER_ADDR_STR_LEN); mac_info->type = mac_type; mac_info->op_type = mac_msg->op_type; msg_hdr->len = sizeof(struct IccpSyncdHDr) + sizeof(struct mclag_fdb_info); @@ -1573,7 +1573,7 @@ int iccp_connect_syncd() count++; - return -1; + return MCLAG_ERROR; } void syncd_info_close() @@ -1598,7 +1598,7 @@ int iccp_get_receive_fdb_sock_fd(struct System *sys) } /*When received MAC add and del packets from mclagsyncd, update mac information*/ -void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint8_t fdb_type, uint8_t op_type) +void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, char *ifname, uint8_t fdb_type, uint8_t op_type) { struct System *sys = NULL; struct CSM *csm = NULL; @@ -1615,10 +1615,6 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint if (!(sys = system_get_instance())) return; - /* Find local itf*/ - if (!(mac_lif = local_if_find_by_name(ifname))) - return; - /* create MAC msg*/ memset(buf, 0, MAX_BUFSIZE); msg_len = sizeof(struct MACMsg); @@ -1627,8 +1623,7 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint mac_msg->fdb_type = fdb_type; sprintf(mac_msg->mac_str, "%s", mac_str); mac_msg->vid = vid; - sprintf(mac_msg->ifname, "%s", mac_lif->name); - sprintf(mac_msg->origin_ifname, "%s", mac_lif->name); + mac_msg->age_flag = 0; /*Debug*/ @@ -1636,7 +1631,6 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint /* dump receive MAC info*/ fprintf(stderr, "\n======== MAC Update==========\n"); fprintf(stderr, " MAC = %s\n", mac_str); - fprintf(stderr, " ifname = %s\n", mac_lif->name); fprintf(stderr, " vlan id = %d\n", vid); fprintf(stderr, " fdb type = %s\n", fdb_type == MAC_TYPE_STATIC ? "static" : "dynamic"); fprintf(stderr, " op type = %s\n", op_type == MAC_SYNC_ADD ? "add" : "del"); @@ -1694,6 +1688,13 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint /*handle mac add*/ if (op_type == MAC_SYNC_ADD) { + /* Find local itf*/ + if (!(mac_lif = local_if_find_by_name(ifname))) + return; + + sprintf(mac_msg->ifname, "%s", ifname); + sprintf(mac_msg->origin_ifname, "%s", ifname); + /*same MAC exist*/ if (mac_exist) { @@ -1848,6 +1849,9 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint /*If local is aged but peer is not aged, Send mac add message to mclagsyncd*/ /*it is from_mclag_intf and port state is up, local orphan mac can not be here*/ + /* Find local itf*/ + if (!(mac_lif = local_if_find_by_name(mac_info->ifname))) + return; if (mac_lif->state == PORT_STATE_UP) add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC); } @@ -1859,60 +1863,46 @@ void do_mac_update_from_syncd(char mac_str[32], uint16_t vid, char *ifname, uint int iccp_receive_fdb_handler_from_syncd(struct System *sys) { - int n = 0; - int count = 0; - int i = 0; char *msg_buf = g_csm_buf; - struct LocalInterface* lif = NULL; - struct IccpSyncdHDr * msg_hdr; + struct IccpSyncdHDr *msg_hdr; struct mclag_fdb_info * mac_info; - static time_t last_time = 0; + size_t pos = 0; + int count = 0; + int i = 0; + int n = 0; if (sys == NULL) - return -1; + return MCLAG_ERROR; + memset(msg_buf, 0, CSM_BUFFER_SIZE); n = read(sys->sync_fd, msg_buf, CSM_BUFFER_SIZE); if (n <= 0) { - if (last_time == 0 || (time(NULL) - last_time) >= 60) - { - ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d read error ret = %d errno = %d ", sys->sync_fd, n, errno); - last_time = time(NULL); - } - - return -1; + ICCPD_LOG_ERR(__FUNCTION__, "read msg error!!!" ); + return MCLAG_ERROR; } - msg_hdr = (struct IccpSyncdHDr *)msg_buf; - ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg version %d type %d len %d ", msg_hdr->ver, msg_hdr->type, msg_hdr->len ); - if (msg_hdr->ver != 1) + while (pos < n) { - ICCPD_LOG_DEBUG(__FUNCTION__, "msg version wrong!!!!! "); - return -1; - } + msg_hdr = (struct IccpSyncdHDr *)&msg_buf[pos]; + if (msg_hdr->ver != 1 || msg_hdr->type != MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION ) + { + ICCPD_LOG_ERR(__FUNCTION__, "msg version or type wrong!!!!! "); + return MCLAG_ERROR; + } - if (msg_hdr->type == MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION) - { count = ( msg_hdr->len - sizeof(struct IccpSyncdHDr )) / sizeof(struct mclag_fdb_info); - ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d ", count ); + ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d ", count); for (i = 0; i < count; i++) { - mac_info = (struct mclag_fdb_info *)&msg_buf[sizeof(struct IccpSyncdHDr ) + i * sizeof(struct mclag_fdb_info)]; + mac_info = (struct mclag_fdb_info *)&msg_buf[pos + sizeof(struct IccpSyncdHDr ) + i * sizeof(struct mclag_fdb_info)]; ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d vid %d mac %s port %s optype %d ", i, mac_info->vid, mac_info->mac, mac_info->port_name, mac_info->op_type); - lif = local_if_find_by_name(mac_info->port_name); - - /*if (!lif ||lif->type != IF_T_PORT_CHANNEL)*/ - if (!lif) - continue; - do_mac_update_from_syncd(mac_info->mac, mac_info->vid, mac_info->port_name, mac_info->type, mac_info->op_type); } - } - else - { - ICCPD_LOG_DEBUG(__FUNCTION__, "recv unknown type msg " ); + + pos += msg_hdr->len; } return 0; @@ -1953,7 +1943,7 @@ int mclagd_ctl_sock_create() int ret = 0; if ((sys = system_get_instance()) == NULL) - return -1; + return MCLAG_ERROR; if (sys->sync_ctrl_fd > 0) return sys->sync_ctrl_fd; @@ -1976,14 +1966,14 @@ int mclagd_ctl_sock_create() { ICCPD_LOG_WARN(__FUNCTION__, "Failed to bind mclagd ctl socket %s:%s\n", sys->mclagdctl_file_path, strerror(errno)); close(sys->sync_ctrl_fd); - return -1; + return MCLAG_ERROR; } if (listen(sys->sync_ctrl_fd, 5) < 0) { ICCPD_LOG_WARN(__FUNCTION__, "Failed to listen unix mclagd ctl socket%s:%s\n", sys->mclagdctl_file_path, strerror(errno)); close(sys->sync_ctrl_fd); - return -1; + return MCLAG_ERROR; } event.data.fd = sys->sync_ctrl_fd; @@ -2005,7 +1995,7 @@ int mclagd_ctl_sock_accept(int fd) if (client_fd < 0) { ICCPD_LOG_WARN(__FUNCTION__, "failed to accept a client from mclagdctl\n"); - return -1; + return MCLAG_ERROR; } return client_fd; @@ -2031,7 +2021,7 @@ int mclagd_ctl_sock_read(int fd, char *r_buf, int total_len) /* error*/ case 0: /* timeout*/ - return -1; + return MCLAG_ERROR; default: break; @@ -2041,7 +2031,7 @@ int mclagd_ctl_sock_read(int fd, char *r_buf, int total_len) ret = read(fd, r_buf + read_len, total_len - read_len); if (ret <= 0) { - return -1; + return MCLAG_ERROR; } read_len += ret; } @@ -2126,7 +2116,7 @@ void mclagd_ctl_handle_dump_arp(int client_fd, int mclag_id) hd->exec_result = ret; hd->info_type = INFO_TYPE_DUMP_ARP; hd->data_len = 0; - mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); if (Pbuf) free(Pbuf); @@ -2166,7 +2156,7 @@ void mclagd_ctl_handle_dump_mac(int client_fd, int mclag_id) hd->exec_result = ret; hd->info_type = INFO_TYPE_DUMP_MAC; hd->data_len = 0; - mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); if (Pbuf) free(Pbuf); @@ -2178,8 +2168,10 @@ void mclagd_ctl_handle_dump_mac(int client_fd, int mclag_id) hd->exec_result = EXEC_TYPE_SUCCESS; hd->info_type = INFO_TYPE_DUMP_MAC; hd->data_len = mac_num * sizeof(struct mclagd_mac_msg); + len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr)); memcpy(Pbuf, &len_tmp, sizeof(int)); + mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len); if (Pbuf) @@ -2206,7 +2198,7 @@ void mclagd_ctl_handle_dump_local_portlist(int client_fd, int mclag_id) hd->exec_result = ret; hd->info_type = INFO_TYPE_DUMP_LOCAL_PORTLIST; hd->data_len = 0; - mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); if (Pbuf) free(Pbuf); @@ -2246,7 +2238,7 @@ void mclagd_ctl_handle_dump_peer_portlist(int client_fd, int mclag_id) hd->exec_result = ret; hd->info_type = INFO_TYPE_DUMP_PEER_PORTLIST; hd->data_len = 0; - mclagd_ctl_sock_write(client_fd, buf, sizeof(struct mclagd_reply_hdr)); + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); if (Pbuf) free(Pbuf); @@ -2276,12 +2268,12 @@ int mclagd_ctl_interactive_process(int client_fd) struct mclagdctl_req_hdr* req = NULL; if (client_fd < 0) - return -1; + return MCLAG_ERROR; ret = mclagd_ctl_sock_read(client_fd, buf, sizeof(struct mclagdctl_req_hdr)); if (ret < 0) - return -1; + return MCLAG_ERROR; req = (struct mclagdctl_req_hdr*)buf; @@ -2310,7 +2302,7 @@ int mclagd_ctl_interactive_process(int client_fd) break; default: - return -1; + return MCLAG_ERROR; } return 0; diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c index 03c3eabfb984..3b4bbbb642c8 100644 --- a/src/iccpd/src/mlacp_sync_prepare.c +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -54,16 +54,16 @@ int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_bu size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncReqTLV); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (buf == NULL) - return -1; + return MCLAG_ERROR; if (msg_len > max_buf_size) - return -1; + return MCLAG_ERROR; if ((sys = system_get_instance()) == NULL) - return -1; + return MCLAG_ERROR; /* Prepare for sync request */ memset(buf, 0, max_buf_size); @@ -106,16 +106,16 @@ int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_s size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSyncDataTLV); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (buf == NULL) - return -1; + return MCLAG_ERROR; if (msg_len > max_buf_size) - return -1; + return MCLAG_ERROR; if ((sys = system_get_instance()) == NULL) - return -1; + return MCLAG_ERROR; /* Prepare for sync request */ memset(buf, 0, max_buf_size); @@ -153,16 +153,16 @@ int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPSysConfigTLV); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (buf == NULL) - return -1; + return MCLAG_ERROR; if (msg_len > max_buf_size) - return -1; + return MCLAG_ERROR; if ((sys = system_get_instance()) == NULL) - return -1; + return MCLAG_ERROR; /* Prepare for sync request */ memset(buf, 0, max_buf_size); @@ -194,22 +194,22 @@ int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_s size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggPortStateTLV); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (buf == NULL) - return -1; + return MCLAG_ERROR; if (local_if == NULL) - return -1; + return MCLAG_ERROR; if (local_if->type != IF_T_PORT_CHANNEL) - return -1; + return MCLAG_ERROR; if (msg_len > max_buf_size) - return -1; + return MCLAG_ERROR; if ((sys = system_get_instance()) == NULL) - return -1; + return MCLAG_ERROR; /* Prepare for sync request */ memset(buf, 0, max_buf_size); @@ -248,13 +248,13 @@ int mlacp_prepare_for_Aggport_config(struct CSM* csm, size_t msg_len = sizeof(ICCHdr) + sizeof(mLACPAggConfigTLV); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (buf == NULL) - return -1; + return MCLAG_ERROR; if (msg_len > max_buf_size) - return -1; + return MCLAG_ERROR; /* Prepare for sync request */ memset(buf, 0, max_buf_size); @@ -287,43 +287,48 @@ int mlacp_prepare_for_Aggport_config(struct CSM* csm, * Preprare Sync MAC-Info TLV * * ***************************************/ -int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg) +int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg, int count) { struct mLACPMACInfoTLV* tlv = NULL; size_t msg_len = 0; size_t tlv_len = 0; ICCHdr* icc_hdr = NULL; + struct mLACPMACData *MacData; if (!csm) - return -1; + return MCLAG_ERROR; if (!buf) - return -1; + return MCLAG_ERROR; - tlv_len = sizeof(struct mLACPMACInfoTLV); + tlv_len = sizeof(struct mLACPMACInfoTLV) + sizeof(struct mLACPMACData) * (count + 1); if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) - return -1; + return MCLAG_ERROR; /* ICC header */ - memset(buf, 0, max_buf_size); icc_hdr = (ICCHdr*)buf; mlacp_fill_icc_header(csm, icc_hdr, msg_len); - /* Prepare for MAC information TLV */ - tlv = (struct mLACPMACInfoTLV*) &buf[sizeof(ICCHdr)]; - memset(tlv, 0, tlv_len); - tlv->icc_parameter.u_bit = 0; - tlv->icc_parameter.f_bit = 0; - tlv->icc_parameter.type = htons(TLV_T_MLACP_MAC_INFO); + tlv = (struct mLACPMACInfoTLV*)&buf[sizeof(ICCHdr)]; tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)); - tlv->type = mac_msg->op_type; - sprintf(tlv->mac_str, "%s", mac_msg->mac_str); - sprintf(tlv->ifname, "%s", mac_msg->origin_ifname); - tlv->vid = htons(mac_msg->vid); - + tlv->num_of_entry = htons(count + 1); + + if (count == 0) + { + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_MAC_INFO); + } + + MacData = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPMACInfoTLV) + sizeof(struct mLACPMACData) * count]; + MacData->type = mac_msg->op_type; + sprintf(MacData->mac_str, "%s", mac_msg->mac_str); + sprintf(MacData->ifname, "%s", mac_msg->origin_ifname); + MacData->vid = htons(mac_msg->vid); + #if 1 ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg type = TLV_T_MLACP_MAC_INFO"); - ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s mac = %s, vid = %d, type = %d", mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s mac = %s, vid = %d, type = %d count %d msg len %d", mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type, count, msg_len); #endif return msg_len; @@ -333,43 +338,50 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu * Preprare Sync ARP-Info TLV * * ***************************************/ -int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg) +int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count) { struct mLACPARPInfoTLV* tlv = NULL; size_t msg_len = 0; size_t tlv_len = 0; ICCHdr* icc_hdr = NULL; + struct ARPMsg* ArpData; if (!csm) - return -1; + return MCLAG_ERROR; if (!buf) - return -1; + return MCLAG_ERROR; - tlv_len = sizeof(struct mLACPARPInfoTLV); + tlv_len = sizeof(struct mLACPARPInfoTLV) + sizeof(struct ARPMsg) * (count + 1); if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) - return -1; + return MCLAG_ERROR; /* ICC header */ - memset(buf, 0, max_buf_size); icc_hdr = (ICCHdr*)buf; mlacp_fill_icc_header(csm, icc_hdr, msg_len); /* Prepare for ARP information TLV */ - tlv = (struct mLACPARPInfoTLV*) &buf[sizeof(ICCHdr)]; - memset(tlv, 0, tlv_len); - tlv->icc_parameter.u_bit = 0; - tlv->icc_parameter.f_bit = 0; - tlv->icc_parameter.type = htons(TLV_T_MLACP_ARP_INFO); + tlv = (struct mLACPARPInfoTLV*)&buf[sizeof(ICCHdr)]; tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter)); - tlv->type = arp_msg->op_type; - sprintf(tlv->ifname, "%s", arp_msg->ifname); - tlv->ipv4_addr = htonl(arp_msg->ipv4_addr); - memcpy(tlv->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); - - ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s msg ifname %s mac =%02x:%02x:%02x:%02x:%02x:%02x ", tlv->ifname, arp_msg->ifname, tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], - tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); - ICCPD_LOG_DEBUG(__FUNCTION__, " IP Addr = %s ", show_ip_str( tlv->ipv4_addr)); + tlv->num_of_entry = htons(count + 1); + + if (count == 0) + { + tlv->icc_parameter.u_bit = 0; + tlv->icc_parameter.f_bit = 0; + tlv->icc_parameter.type = htons(TLV_T_MLACP_ARP_INFO); + } + + ArpData = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPARPInfoTLV) + sizeof(struct ARPMsg) * count]; + + ArpData->op_type = arp_msg->op_type; + sprintf(ArpData->ifname, "%s", arp_msg->ifname); + ArpData->ipv4_addr = htonl(arp_msg->ipv4_addr); + memcpy(ArpData->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); + + ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s mac =%02x:%02x:%02x:%02x:%02x:%02x ", ArpData->ifname, ArpData->mac_addr[0], ArpData->mac_addr[1], ArpData->mac_addr[2], + ArpData->mac_addr[3], ArpData->mac_addr[4], ArpData->mac_addr[5]); + ICCPD_LOG_DEBUG(__FUNCTION__, " IP Addr = %s ", show_ip_str( ArpData->ipv4_addr)); return msg_len; } @@ -392,15 +404,15 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, int num_of_vlan_id = 0; if (csm == NULL ) - return -1; + return MCLAG_ERROR; if (buf == NULL ) - return -1; + return MCLAG_ERROR; if (port_channel == NULL ) - return -1; + return MCLAG_ERROR; if (port_channel->type == IF_T_PORT) - return -1; + return MCLAG_ERROR; if ((sys = system_get_instance()) == NULL ) - return -1; + return MCLAG_ERROR; /* Calculate VLAN ID Length */ LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next) @@ -410,7 +422,7 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, tlv_len = sizeof(struct mLACPPortChannelInfoTLV) + sizeof(struct mLACPVLANData) * num_of_vlan_id; if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) - return -1; + return MCLAG_ERROR; /* Prepare for port channel info */ memset(buf, 0, max_buf_size); @@ -469,13 +481,13 @@ int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, size_t tlv_len; if (csm == NULL ) - return -1; + return MCLAG_ERROR; if (buf == NULL ) - return -1; + return MCLAG_ERROR; if (peerlink_port == NULL ) - return -1; + return MCLAG_ERROR; if ((sys = system_get_instance()) == NULL ) - return -1; + return MCLAG_ERROR; /* Prepare for port channel info */ memset(buf, 0, max_buf_size); @@ -483,7 +495,7 @@ int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, tlv_len = sizeof(struct mLACPPeerLinkInfoTLV); if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size) - return -1; + return MCLAG_ERROR; icc_hdr = (ICCHdr*)buf; tlv = (struct mLACPPeerLinkInfoTLV*)&buf[sizeof(ICCHdr)]; @@ -519,16 +531,16 @@ int mlacp_prepare_for_heartbeat(struct CSM* csm, char* buf, size_t max_buf_size) size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPHeartbeatTLV); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (buf == NULL) - return -1; + return MCLAG_ERROR; if (msg_len > max_buf_size) - return -1; + return MCLAG_ERROR; if ((sys = system_get_instance()) == NULL) - return -1; + return MCLAG_ERROR; /* Prepare for sync request */ memset(buf, 0, max_buf_size); @@ -561,16 +573,16 @@ int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_siz size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPWarmbootTLV); if (csm == NULL) - return -1; + return MCLAG_ERROR; if (buf == NULL) - return -1; + return MCLAG_ERROR; if (msg_len > max_buf_size) - return -1; + return MCLAG_ERROR; if ((sys = system_get_instance()) == NULL) - return -1; + return MCLAG_ERROR; /* Prepare for sync request */ memset(buf, 0, max_buf_size); @@ -598,7 +610,7 @@ int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_siz static int mlacp_fill_icc_header(struct CSM* csm, ICCHdr* icc_hdr, size_t msg_len) { if (csm == NULL || icc_hdr == NULL) - return -1; + return MCLAG_ERROR; /* ICC header */ icc_hdr->ldp_hdr.u_bit = 0x0; diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c index 11320f97d1a7..b6bee1a97e92 100644 --- a/src/iccpd/src/mlacp_sync_update.c +++ b/src/iccpd/src/mlacp_sync_update.c @@ -101,7 +101,7 @@ int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf) { pif = peer_if_create(csm, ntohs(portconf->agg_id), IF_T_PORT_CHANNEL); if (pif == NULL) - return -1; + return MCLAG_ERROR; new_create = 1; } @@ -128,7 +128,7 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) uint8_t po_active; if (csm == NULL || tlv == NULL) - return -255; + return MCLAG_ERROR; ICCPD_LOG_DEBUG(__FUNCTION__, " po id %d state %d ", ntohs(tlv->agg_id), tlv->agg_state); po_active = (tlv->agg_state == PORT_STATE_UP); @@ -158,26 +158,24 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) /***************************************** * Recv from peer, MAC-Info Update * ***************************************/ -int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* tlv) +int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData *MacData) { + struct Msg* msg = NULL; struct MACMsg *mac_msg = NULL, mac_data; struct LocalInterface* local_if = NULL; uint8_t from_mclag_intf = 0;/*0: orphan port, 1: MCLAG port*/ - if (!csm || !tlv) - return -255; - #if 1 ICCPD_LOG_INFO(__FUNCTION__, "Received MAC Info, itf=[%s] vid[%d] MAC[%s] type %d ", - tlv->ifname, ntohs(tlv->vid), tlv->mac_str, tlv->type); + MacData->ifname, ntohs(MacData->vid), MacData->mac_str, MacData->type); #endif /*Find the interface in MCLAG interface list*/ LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) { - if (local_if->type == IF_T_PORT_CHANNEL && strcmp(local_if->name, tlv->ifname) == 0) + if (local_if->type == IF_T_PORT_CHANNEL && strcmp(local_if->name, MacData->ifname) == 0) { from_mclag_intf = 1; break; @@ -190,9 +188,9 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* mac_msg = (struct MACMsg*)msg->buf; /*Same MAC is exist in local switch, this may be mac move*/ - if (strcmp(mac_msg->mac_str, tlv->mac_str) == 0 && mac_msg->vid == ntohs(tlv->vid)) + if (strcmp(mac_msg->mac_str, MacData->mac_str) == 0 && mac_msg->vid == ntohs(MacData->vid)) { - if (tlv->type == MAC_SYNC_ADD) + if (MacData->type == MAC_SYNC_ADD) { mac_msg->age_flag &= ~MAC_AGE_PEER; ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", @@ -200,12 +198,12 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* /*mac_msg->fdb_type = tlv->fdb_type;*/ /*The port ifname is different to the local item*/ - if (strcmp(mac_msg->ifname, tlv->ifname) != 0 || strcmp(mac_msg->origin_ifname, tlv->ifname) != 0) + if (strcmp(mac_msg->ifname, MacData->ifname) != 0 || strcmp(mac_msg->origin_ifname, MacData->ifname) != 0) { if (mac_msg->fdb_type != MAC_TYPE_STATIC) { /*Update local item*/ - memcpy(&mac_msg->origin_ifname, tlv->ifname, MAX_L_PORT_NAME); + memcpy(&mac_msg->origin_ifname, MacData->ifname, MAX_L_PORT_NAME); } /*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/ @@ -240,7 +238,7 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* del_mac_from_chip(mac_msg); /*Update local item*/ - memcpy(&mac_msg->ifname, tlv->ifname, MAX_L_PORT_NAME); + memcpy(&mac_msg->ifname, MacData->ifname, MAX_L_PORT_NAME); /*if orphan port mac but no peerlink, don't keep this mac*/ if (from_mclag_intf == 0) @@ -255,7 +253,7 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* else { /*Update local item*/ - memcpy(&mac_msg->ifname, tlv->ifname, MAX_L_PORT_NAME); + memcpy(&mac_msg->ifname, MacData->ifname, MAX_L_PORT_NAME); /*from MCLAG port and the local port is up, add mac to ASIC to update port*/ add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC); @@ -288,7 +286,7 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* } /* delete/add MAC list*/ - if (msg && tlv->type == MAC_SYNC_DEL) + if (msg && MacData->type == MAC_SYNC_DEL) { mac_msg->age_flag |= MAC_AGE_PEER; ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %d ifname %s, add %s vlan-id %d, op_type %d", @@ -309,14 +307,14 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* return 0; } } - else if (!msg && tlv->type == MAC_SYNC_ADD) + else if (!msg && MacData->type == MAC_SYNC_ADD) { mac_msg = (struct MACMsg*)&mac_data; mac_msg->fdb_type = MAC_TYPE_DYNAMIC; - mac_msg->vid = ntohs(tlv->vid); - sprintf(mac_msg->mac_str, "%s", tlv->mac_str); - sprintf(mac_msg->ifname, "%s", tlv->ifname); - sprintf(mac_msg->origin_ifname, "%s", tlv->ifname); + mac_msg->vid = ntohs(MacData->vid); + sprintf(mac_msg->mac_str, "%s", MacData->mac_str); + sprintf(mac_msg->ifname, "%s", MacData->ifname); + sprintf(mac_msg->origin_ifname, "%s", MacData->ifname); mac_msg->age_flag = 0; /*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/ @@ -327,8 +325,8 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* if (strlen(csm->peer_itf_name) == 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "orphan port or portchannel is down, but peer-link is not configured: ifname %s, add %s vlan-id %d, op_type %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "orphan port %d or portchannel is down, but peer-link is not configured: ifname %s, add %s vlan-id %d, op_type %d", + from_mclag_intf, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); /*if orphan port mac but no peerlink, don't keep this mac*/ if (from_mclag_intf == 0) @@ -378,6 +376,22 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* return 0; } +int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* tlv) +{ + int count = 0; + int i; + + if (!csm || !tlv) + return MCLAG_ERROR; + count = ntohs(tlv->num_of_entry); + ICCPD_LOG_INFO(__FUNCTION__, "Received MAC Info count %d ", count ); + + for (i = 0; i < count; i++) + { + mlacp_fsm_update_mac_entry_from_peer(csm, &(tlv->MacEntry[i])); + } +} + /***************************************** * Tool : Add ARP Info into ARP list * @@ -407,7 +421,7 @@ void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg) /***************************************** * ARP-Info Update * ***************************************/ -int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) +int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) { struct Msg* msg = NULL; struct ARPMsg *arp_msg = NULL, arp_data; @@ -417,23 +431,23 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) int set_arp_flag = 0; char mac_str[18] = ""; - if (!csm || !tlv) - return -255; + if (!csm || !arp_entry) + return MCLAG_ERROR; #if 1 ICCPD_LOG_INFO(__FUNCTION__, "%s: Received ARP Info," "itf=[%s] ARP IP[%s],MAC[%02x:%02x:%02x:%02x:%02x:%02x]", __FUNCTION__, - tlv->ifname, show_ip_str(tlv->ipv4_addr), - tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], - tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), + arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2], + arp_entry->mac_addr[3], arp_entry->mac_addr[4], arp_entry->mac_addr[5]); #endif - sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", tlv->mac_addr[0], tlv->mac_addr[1], tlv->mac_addr[2], - tlv->mac_addr[3], tlv->mac_addr[4], tlv->mac_addr[5]); + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2], + arp_entry->mac_addr[3], arp_entry->mac_addr[4], arp_entry->mac_addr[5]); - if (strncmp(tlv->ifname, "Vlan", 4) == 0) + if (strncmp(arp_entry->ifname, "Vlan", 4) == 0) { peer_link_if = local_if_find_by_name(csm->peer_itf_name); @@ -444,7 +458,7 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) { if (!vlan_id_list->vlan_itf) continue; - if (strcmp(vlan_id_list->vlan_itf->name, tlv->ifname) != 0) + if (strcmp(vlan_id_list->vlan_itf->name, arp_entry->ifname) != 0) continue; if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) continue; @@ -475,7 +489,7 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) { if (!vlan_id_list->vlan_itf) continue; - if (strcmp(vlan_id_list->vlan_itf->name, tlv->ifname) != 0) + if (strcmp(vlan_id_list->vlan_itf->name, arp_entry->ifname) != 0) continue; if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) continue; @@ -497,7 +511,7 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) else { /* Is the ARP belong to a L3 mode MLAG itf?*/ - if (strcmp(local_if->name, tlv->ifname) == 0) + if (strcmp(local_if->name, arp_entry->ifname) == 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ==> Find ARP itf on L3 port-channel, %s", @@ -522,27 +536,27 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) /* set dynamic ARP*/ if (set_arp_flag == 1) { - if (tlv->type == ARP_SYNC_ADD) + if (arp_entry->op_type == ARP_SYNC_ADD) { - if (mlacp_fsm_arp_set(tlv->ifname, ntohl(tlv->ipv4_addr), mac_str) < 0) + if (mlacp_fsm_arp_set(arp_entry->ifname, ntohl(arp_entry->ipv4_addr), mac_str) < 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP set for %s %s %s", - __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); - return -1; + __FUNCTION__, arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); + return MCLAG_ERROR; } } else { - if (mlacp_fsm_arp_del(tlv->ifname, ntohl(tlv->ipv4_addr)) < 0) + if (mlacp_fsm_arp_del(arp_entry->ifname, ntohl(arp_entry->ipv4_addr)) < 0) { ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP delete for %s %s %s", - __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); - return -1; + __FUNCTION__, arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); + return MCLAG_ERROR; } } ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP update for %s %s %s", - __FUNCTION__, tlv->ifname, show_ip_str(tlv->ipv4_addr), mac_str); + __FUNCTION__, arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); } else { @@ -555,30 +569,30 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) TAILQ_FOREACH(msg, &(MLACP(csm).arp_list), tail) { arp_msg = (struct ARPMsg*)msg->buf; - if (arp_msg->ipv4_addr == ntohl(tlv->ipv4_addr)) + if (arp_msg->ipv4_addr == ntohl(arp_entry->ipv4_addr)) { /*arp_msg->op_type = tlv->type;*/ - sprintf(arp_msg->ifname, "%s", tlv->ifname); - memcpy(arp_msg->mac_addr, tlv->mac_addr, ETHER_ADDR_LEN); + sprintf(arp_msg->ifname, "%s", arp_entry->ifname); + memcpy(arp_msg->mac_addr, arp_entry->mac_addr, ETHER_ADDR_LEN); break; } } /* delete/add ARP list*/ - if (msg && tlv->type == ARP_SYNC_DEL) + if (msg && arp_entry->op_type == ARP_SYNC_DEL) { TAILQ_REMOVE(&(MLACP(csm).arp_list), msg, tail); free(msg->buf); free(msg); ICCPD_LOG_INFO(__FUNCTION__, "%s: del arp queue successfully", __FUNCTION__); } - else if (!msg && tlv->type == ARP_SYNC_ADD) + else if (!msg && arp_entry->op_type == ARP_SYNC_ADD) { arp_msg = (struct ARPMsg*)&arp_data; - sprintf(arp_msg->ifname, "%s", tlv->ifname); - arp_msg->ipv4_addr = ntohl(tlv->ipv4_addr); - arp_msg->op_type = tlv->type; - memcpy(arp_msg->mac_addr, tlv->mac_addr, ETHER_ADDR_LEN); + sprintf(arp_msg->ifname, "%s", arp_entry->ifname); + arp_msg->ipv4_addr = ntohl(arp_entry->ipv4_addr); + arp_msg->op_type = arp_entry->op_type; + memcpy(arp_msg->mac_addr, arp_entry->mac_addr, ETHER_ADDR_LEN); if (iccp_csm_init_msg(&msg, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) { mlacp_enqueue_arp(csm, msg); @@ -591,7 +605,7 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) { arp_msg = (struct ARPMsg*)msg->buf; - if (arp_msg->ipv4_addr == ntohl(tlv->ipv4_addr)) + if (arp_msg->ipv4_addr == ntohl(arp_entry->ipv4_addr)) break; } @@ -604,7 +618,7 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail) { arp_msg = (struct ARPMsg*)msg->buf; - if (arp_msg->ipv4_addr == ntohl(tlv->ipv4_addr)) + if (arp_msg->ipv4_addr == ntohl(arp_entry->ipv4_addr)) break; } } @@ -612,6 +626,22 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) return 0; } +int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv) +{ + int count = 0; + int i; + + if (!csm || !tlv) + return MCLAG_ERROR; + count = ntohs(tlv->num_of_entry); + ICCPD_LOG_INFO(__FUNCTION__, "Received ARP Info count %d ", count ); + + for (i = 0; i < count; i++) + { + mlacp_fsm_update_arp_entry(csm, &(tlv->ArpEntry[i])); + } +} + /***************************************** * Port-Channel-Info Update * ***************************************/ @@ -623,7 +653,7 @@ int mlacp_fsm_update_port_channel_info(struct CSM* csm, int i = 0; if (csm == NULL || tlv == NULL ) - return -1; + return MCLAG_ERROR; LIST_FOREACH(peer_if, &(MLACP(csm).pif_list), mlacp_next) { @@ -665,7 +695,7 @@ int mlacp_fsm_update_peerlink_info(struct CSM* csm, struct mLACPPeerLinkInfoTLV* tlv) { if (csm == NULL || tlv == NULL ) - return -1; + return MCLAG_ERROR; if (!csm->peer_link_if) { @@ -688,7 +718,7 @@ int mlacp_fsm_update_peerlink_info(struct CSM* csm, int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv) { if (!csm || !tlv) - return -255; + return MCLAG_ERROR; time(&csm->heartbeat_update_time); @@ -701,7 +731,7 @@ int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv) int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv) { if (!csm || !tlv) - return -255; + return MCLAG_ERROR; time(&csm->peer_warm_reboot_time); diff --git a/src/iccpd/src/port.c b/src/iccpd/src/port.c index 64492d2a5e1b..c05e3e6eaaa1 100644 --- a/src/iccpd/src/port.c +++ b/src/iccpd/src/port.c @@ -364,7 +364,8 @@ void local_if_destroy(char *ifname) else local_if_remove(lif); - if (csm->peer_link_if && strcmp(csm->peer_link_if->name, ifname) == 0) + csm = lif->csm; + if (csm && csm->peer_link_if && strcmp(csm->peer_link_if->name, ifname) == 0) { /*if the peerlink interface is not created, peer connection can not establish*/ scheduler_session_disconnect_handler(csm); @@ -372,7 +373,6 @@ void local_if_destroy(char *ifname) csm->peer_link_if = NULL; } - csm = lif->csm; if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) goto to_mlacp_purge; else @@ -581,7 +581,7 @@ int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) { vlan = (struct VLAN_ID*)malloc(sizeof(struct VLAN_ID)); if (!vlan) - return -1; + return MCLAG_ERROR; ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d on %s", vid, local_if->name); local_if->port_config_sync = 1; @@ -655,7 +655,7 @@ int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) { peer_vlan = (struct VLAN_ID*)malloc(sizeof(struct VLAN_ID)); if (!peer_vlan) - return -1; + return MCLAG_ERROR; ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d from peer's %s", vlan_id, peer_if->name); LIST_INSERT_HEAD(&(peer_if->vlan_list), peer_vlan, port_next); @@ -705,7 +705,7 @@ int set_sys_arp_accept_flag(char* ifname, int flag) char cmd[64]; char arp_file[64]; char buf[2]; - int result = -1; + int result = MCLAG_ERROR; memset(arp_file, 0, 64); snprintf(arp_file, 63, "/proc/sys/net/ipv4/conf/%s/arp_accept", ifname); diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c index 256351b9e062..3446f34404ba 100644 --- a/src/iccpd/src/scheduler.c +++ b/src/iccpd/src/scheduler.c @@ -98,7 +98,7 @@ static int scheduler_transit_fsm() struct System* sys = NULL; if ((sys = system_get_instance()) == NULL) - return -1; + return MCLAG_ERROR; LIST_FOREACH(csm, &(sys->csm_list), next) { @@ -133,7 +133,7 @@ int scheduler_csm_read_callback(struct CSM* csm) int recv_len = 0, len = 0, retval; if (csm->sock_fd <= 0) - return -1; + return MCLAG_ERROR; memset(peer_msg, 0, CSM_BUFFER_SIZE); @@ -190,14 +190,14 @@ int scheduler_csm_read_callback(struct CSM* csm) recv_err: scheduler_session_disconnect_handler(csm); - return -1; + return MCLAG_ERROR; } /* Handle server accept client */ int scheduler_server_accept() { int new_fd; - int ret = -1; + int ret = MCLAG_ERROR; struct CSM* csm = NULL; struct System* sys = NULL; struct sockaddr_in client_addr; @@ -205,11 +205,11 @@ int scheduler_server_accept() if ((sys = system_get_instance()) == NULL ) { - return -1; + return MCLAG_ERROR; } if (sys->server_fd <= 0) { - return -1; + return MCLAG_ERROR; } addr_len = sizeof(struct sockaddr_in); @@ -249,7 +249,7 @@ int scheduler_server_accept() reject_client: if (new_fd >= 0) close(new_fd); - return -1; + return MCLAG_ERROR; accept_client: session_conn_thread_lock(&csm->conn_mutex); @@ -559,7 +559,7 @@ void session_client_conn_handler(struct CSM *csm) /* Create socket connect to peer */ int scheduler_prepare_session(struct CSM* csm) { - int ret = -1; + int ret = MCLAG_ERROR; uint32_t local_ip = 0; uint32_t peer_ip = 0; @@ -676,24 +676,24 @@ int scheduler_check_csm_config(struct CSM* csm) struct System* sys = NULL; if ((sys = system_get_instance()) == NULL) - return -1; + return MCLAG_ERROR; if (csm == NULL ) - return -1; + return MCLAG_ERROR; if (csm->mlag_id <= 0) - ret = -1; + ret = MCLAG_ERROR; else if (strlen(csm->peer_ip) <= 0) - ret = -1; + ret = MCLAG_ERROR; else if (strlen(csm->sender_ip) <= 0) - ret = -1; + ret = MCLAG_ERROR; else if (strlen(csm->peer_itf_name) != 0) { lif = local_if_find_by_name(csm->peer_itf_name); if (lif == NULL) { /*if peer-link is configured but the interface is not created, peer connection can not establish*/ - return -1; + return MCLAG_ERROR; } else { @@ -702,7 +702,7 @@ int scheduler_check_csm_config(struct CSM* csm) } } - if (ret == -1) + if (ret == MCLAG_ERROR) ICCPD_LOG_INFO(__FUNCTION__, "mclag config is not complete or conflicting, please check!"); /* Decide STP role*/ @@ -716,11 +716,11 @@ int scheduler_unregister_sock_read_event_callback(struct CSM* csm) struct System* sys = NULL; if ((sys = system_get_instance()) == NULL ) - return -1; + return MCLAG_ERROR; if (csm == NULL ) { - return -2; + return MCLAG_ERROR; } FD_CLR(csm->sock_fd, &(sys->readfd)); From f20e570e599e8f39ca6c5f6d8ae6d69e734eaad4 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 29 Aug 2019 19:53:31 -0700 Subject: [PATCH 14/23] * optimize warm-reboot process * estabish iccpd connection with configurated src-ip Signed-off-by: shine.chen --- src/iccpd/include/iccp_csm.h | 1 + src/iccpd/include/msg_format.h | 6 +-- src/iccpd/src/iccp_csm.c | 1 + src/iccpd/src/mclagdctl/mclagdctl.c | 4 +- src/iccpd/src/mlacp_fsm.c | 22 +++++++-- src/iccpd/src/mlacp_link_handler.c | 72 +++++++++++++++-------------- src/iccpd/src/mlacp_sync_update.c | 8 ++++ src/iccpd/src/scheduler.c | 11 +++++ 8 files changed, 82 insertions(+), 43 deletions(-) diff --git a/src/iccpd/include/iccp_csm.h b/src/iccpd/include/iccp_csm.h index 33db3717be24..9cf1022dd10c 100644 --- a/src/iccpd/include/iccp_csm.h +++ b/src/iccpd/include/iccp_csm.h @@ -108,6 +108,7 @@ struct CSM time_t heartbeat_send_time; time_t heartbeat_update_time; time_t peer_warm_reboot_time; + time_t warm_reboot_disconn_time; char peer_itf_name[IFNAMSIZ]; char peer_ip[INET_ADDRSTRLEN]; char sender_ip[INET_ADDRSTRLEN]; diff --git a/src/iccpd/include/msg_format.h b/src/iccpd/include/msg_format.h index 3f2458d07325..5f4deb18772b 100644 --- a/src/iccpd/include/msg_format.h +++ b/src/iccpd/include/msg_format.h @@ -25,7 +25,7 @@ #define MSG_FORMAT_H_ #include #include - +#include "../include/port.h" #define MAX_MSG_LOG_SIZE 128 @@ -474,9 +474,9 @@ typedef struct mclag_sub_option_hdr_t_ struct mclag_fdb_info { - char mac[32]; + char mac[ETHER_ADDR_STR_LEN]; unsigned int vid; - char port_name[32]; + char port_name[MAX_L_PORT_NAME]; short type; /*dynamic or static*/ short op_type; /*add or del*/ }; diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c index c4da855b98a1..9dbc144ea4bb 100644 --- a/src/iccpd/src/iccp_csm.c +++ b/src/iccpd/src/iccp_csm.c @@ -140,6 +140,7 @@ void iccp_csm_status_reset(struct CSM* csm, int all) csm->heartbeat_send_time = 0; csm->heartbeat_update_time = 0; csm->peer_warm_reboot_time = 0; + csm->warm_reboot_disconn_time = 0; csm->role_type = STP_ROLE_NONE; csm->sock_read_event_ptr = NULL; csm->peer_link_if = NULL; diff --git a/src/iccpd/src/mclagdctl/mclagdctl.c b/src/iccpd/src/mclagdctl/mclagdctl.c index bf0e6528d6bf..e2d098cf429f 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.c +++ b/src/iccpd/src/mclagdctl/mclagdctl.c @@ -410,7 +410,7 @@ int mclagdctl_parse_dump_local_portlist(char *msg, int data_len) fprintf(stdout, "\n"); - if (memcmp(lif_info->type, "PORT-CHANNEL", 12) == 0) + if (memcmp(lif_info->type, "PortChannel", 11) == 0) { fprintf(stdout, "%s: %d\n", "Ifindex", lif_info->ifindex); fprintf(stdout, "%s: %s\n", "Type", lif_info->type); @@ -425,7 +425,7 @@ int mclagdctl_parse_dump_local_portlist(char *msg, int data_len) fprintf(stdout, "%s: %d\n", "Prefixlen", lif_info->prefixlen); fprintf(stdout, "%s: %s\n", "State", lif_info->state); fprintf(stdout, "%s: %s\n", "IsL3Interface", lif_info->l3_mode ? "Yes" : "No"); - fprintf(stdout, "%s: %s\n", "IsPeerlink", lif_info->is_peer_link ? "Yes" : "No"); + /*fprintf(stdout, "%s: %s\n", "IsPeerlink", lif_info->is_peer_link ? "Yes" : "No");*/ fprintf(stdout, "%s: %s\n", "MemberPorts", lif_info->portchannel_member_buf); /*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id); fprintf(stdout,"%s: %d\n" ,"PortchannelIsUp", lif_info->po_active); diff --git a/src/iccpd/src/mlacp_fsm.c b/src/iccpd/src/mlacp_fsm.c index d5c6f254945d..46a06c198da1 100644 --- a/src/iccpd/src/mlacp_fsm.c +++ b/src/iccpd/src/mlacp_fsm.c @@ -93,6 +93,8 @@ LIST_INIT(&(list)); \ } +#define WARM_REBOOT_TIMEOUT 90 + /***************************************** * Static Function * @@ -594,6 +596,17 @@ void mlacp_fsm_transit(struct CSM* csm) return; } + if (csm->warm_reboot_disconn_time != 0) + { + /*After peer warm reboot and disconnect, if peer connection is not establised more than 90s, + recover peer disconnection to normal process, such as add peer age flag for MACs etc*/ + if ((time(NULL) - csm->warm_reboot_disconn_time) >= WARM_REBOOT_TIMEOUT) + { + csm->warm_reboot_disconn_time = 0; + mlacp_peer_disconn_handler(csm); + } + } + mlacp_sync_send_heartbeat(csm); /* Dequeue msg if any*/ @@ -636,7 +649,6 @@ void mlacp_fsm_transit(struct CSM* csm) { MLACP(csm).wait_for_sync_data = 0; MLACP(csm).current_state = MLACP_STATE_STAGE1; - mlacp_resync_mac(csm); mlacp_resync_arp(csm); } @@ -1184,10 +1196,12 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) /*If peer is warm reboot*/ if (csm->peer_warm_reboot_time != 0) { - /*Peer warm reboot timeout, recover to normal reboot*/ - if ((time(NULL) - csm->peer_warm_reboot_time) >= 90) + /*Peer warm reboot timeout(connection is not broken more than 90s), recover to normal reboot*/ + if ((time(NULL) - csm->peer_warm_reboot_time) >= WARM_REBOOT_TIMEOUT) + { csm->peer_warm_reboot_time = 0; + } } return; -} \ No newline at end of file +} diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index f7a25826b451..0f9e6b4d76e2 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -1066,45 +1066,39 @@ uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t if (set == 0)/*remove age flag*/ { - if (new_age_flag & MAC_AGE_LOCAL) - { - new_age_flag &= ~MAC_AGE_LOCAL; + new_age_flag &= ~MAC_AGE_LOCAL; - ICCPD_LOG_DEBUG(__FUNCTION__, "Remove local age flag: %d ifname %s, add %s vlan-id %d, age_flag %d", + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove local age flag: %d ifname %s, add %s vlan-id %d, age_flag %d", new_age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); - /*send mac MAC_SYNC_ADD message to peer*/ - if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + /*send mac MAC_SYNC_ADD message to peer*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { - mac_msg->op_type = MAC_SYNC_ADD; - if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) - { - TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); - } + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); } } } else/*set age flag*/ { - if (!(new_age_flag & MAC_AGE_LOCAL)) - { - new_age_flag |= MAC_AGE_LOCAL; + new_age_flag |= MAC_AGE_LOCAL; - ICCPD_LOG_DEBUG(__FUNCTION__, "Add local age flag: %s, add %s vlan-id %d, age_flag %d", + ICCPD_LOG_DEBUG(__FUNCTION__, "Add local age flag: %s, add %s vlan-id %d, age_flag %d", mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); - /*send mac MAC_SYNC_DEL message to peer*/ - if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + /*send mac MAC_SYNC_DEL message to peer*/ + if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) + { + mac_msg->op_type = MAC_SYNC_DEL; + if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { - mac_msg->op_type = MAC_SYNC_DEL; - if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) - { - TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); - } + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); } } } @@ -1293,6 +1287,12 @@ void mlacp_peer_conn_handler(struct CSM* csm) if ((sys = system_get_instance()) == NULL) return; + if (csm->warm_reboot_disconn_time != 0) + { + /*If peer reconnected, reset peer disconnect time*/ + csm->warm_reboot_disconn_time = 0; + } + if (csm->peer_link_if) { set_peerlink_mlag_port_learn(csm->peer_link_if, 0); @@ -1308,6 +1308,7 @@ void mlacp_peer_conn_handler(struct CSM* csm) } iccp_get_fdb_change_from_syncd(); + sys->csm_trans_time = time(NULL); mlacp_conn_handler_fdb(csm); @@ -1367,14 +1368,6 @@ void mlacp_peer_disconn_handler(struct CSM* csm) if (sys->warmboot_exit == WARM_REBOOT) return; - /*If peer is warm reboot, don't change FDB and MAC address*/ - if (csm->peer_warm_reboot_time != 0) - { - /*If peer disconnected, recover peer to normal reboot for next time*/ - csm->peer_warm_reboot_time = 0; - return; - } - TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { mac_msg = (struct MACMsg*)msg->buf; @@ -1398,6 +1391,17 @@ void mlacp_peer_disconn_handler(struct CSM* csm) free(msg); } + /*If peer is warm reboot, only set peer age flag to MACs*/ + if (csm->peer_warm_reboot_time != 0) + { + /*If peer disconnected, recover peer to normal reboot for next time*/ + csm->peer_warm_reboot_time = 0; + /*peer connection must be establised again within 90s + from last disconnection for peer warm reboot*/ + time(&csm->warm_reboot_disconn_time); + return; + } + /* Clean all port block*/ peerlink_port_isolate_cleanup(csm); diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c index b6bee1a97e92..404e2dda6e9b 100644 --- a/src/iccpd/src/mlacp_sync_update.c +++ b/src/iccpd/src/mlacp_sync_update.c @@ -252,6 +252,9 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * } else { + /*Remove MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 0); + /*Update local item*/ memcpy(&mac_msg->ifname, MacData->ifname, MAX_L_PORT_NAME); @@ -341,6 +344,11 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); } } + else + { + /*Remove MAC_AGE_LOCAL flag*/ + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 0); + } if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c index 3446f34404ba..a991ac9992c4 100644 --- a/src/iccpd/src/scheduler.c +++ b/src/iccpd/src/scheduler.c @@ -488,6 +488,12 @@ void session_client_conn_handler(struct CSM *csm) struct timeval con_tv; socklen_t len = sizeof(con_tv); + struct sockaddr_in src_addr; + bzero(&(src_addr), sizeof(src_addr)); + src_addr.sin_family = PF_INET; + src_addr.sin_port = 0; + src_addr.sin_addr.s_addr = inet_addr(csm->sender_ip); + /* Lock the thread*/ session_conn_thread_lock(&csm->conn_mutex); @@ -516,6 +522,11 @@ void session_client_conn_handler(struct CSM *csm) ICCPD_LOG_INFO(__FUNCTION__, "Set socket timeout fail"); } + if (bind(connFd, (struct sockaddr*)&(src_addr), sizeof(src_addr)) < 0) + { + ICCPD_LOG_INFO(__FUNCTION__, "Bind socket failed. Error"); + } + /* Try conn*/ ICCPD_LOG_INFO(__FUNCTION__, "Connecting. peer ip = [%s], %p", csm->peer_ip, csm); connStat = connect(connFd, (struct sockaddr*)&(peer_addr), sizeof(peer_addr)); From 2cdea01122e1a46005c1a371d27195705722e733 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 5 Sep 2019 00:14:19 -0700 Subject: [PATCH 15/23] fix a typo Signed-off-by: shine.chen --- src/iccpd/src/scheduler.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c index a991ac9992c4..557090846bd9 100644 --- a/src/iccpd/src/scheduler.c +++ b/src/iccpd/src/scheduler.c @@ -629,16 +629,16 @@ void scheduler_server_sock_init() { int optval = 1; struct System* sys = NULL; - struct sockaddr_in svr_addr; + struct sockaddr_in src_addr; if ((sys = system_get_instance()) == NULL) return; sys->server_fd = socket(PF_INET, SOCK_STREAM, 0); - bzero(&(svr_addr), sizeof(svr_addr)); - svr_addr.sin_family = PF_INET; - svr_addr.sin_port = htons(ICCP_TCP_PORT); - svr_addr.sin_addr.s_addr = INADDR_ANY; + bzero(&(src_addr), sizeof(src_addr)); + src_addr.sin_family = PF_INET; + src_addr.sin_port = htons(ICCP_TCP_PORT); + src_addr.sin_addr.s_addr = INADDR_ANY; if (sys->server_fd == -1) { @@ -652,7 +652,7 @@ void scheduler_server_sock_init() /*return;*/ } - if (bind(sys->server_fd, (struct sockaddr*)&(svr_addr), sizeof(svr_addr)) < 0) + if (bind(sys->server_fd, (struct sockaddr*)&(src_addr), sizeof(src_addr)) < 0) { ICCPD_LOG_INFO(__FUNCTION__, "Bind socket failed. Error"); return; From b61688ba0f11ee757e5578cad83d909befaeafa3 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Wed, 11 Sep 2019 02:14:53 -0700 Subject: [PATCH 16/23] optimize some code * add some debug info * optimize bridge mac setting * fix vlan mac sync issue on standby node Signed-off-by: shine.chen --- src/iccpd/src/iccp_cli.c | 6 ------ src/iccpd/src/iccp_csm.c | 5 ++++- src/iccpd/src/mlacp_fsm.c | 2 ++ src/iccpd/src/mlacp_link_handler.c | 27 +++++++++++++++++++++++++++ src/iccpd/src/mlacp_sync_prepare.c | 2 ++ src/iccpd/src/mlacp_sync_update.c | 1 + src/iccpd/src/port.c | 3 +++ src/iccpd/src/scheduler.c | 7 +++++-- 8 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c index ba0995b50451..0127482125a6 100644 --- a/src/iccpd/src/iccp_cli.c +++ b/src/iccpd/src/iccp_cli.c @@ -480,12 +480,6 @@ int set_local_system_id(const char* mac) MLACP(csm).system_id[3], MLACP(csm).system_id[4], MLACP(csm).system_id[5]); } - /*When changing the mac of a vlan member port, the mac of Bridge will be changed.*/ - /*The Bridge mac can not be the same as peer system id, so fix the Bridge MAC address here.*/ - sprintf(syscmd, "ip link set dev Bridge address %s > /dev/null 2>&1", mac); - ret = system(syscmd); - ICCPD_LOG_DEBUG(__FUNCTION__, " %s ret = %d", syscmd, ret); - return 0; } diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c index 9dbc144ea4bb..e95aa7fa158e 100644 --- a/src/iccpd/src/iccp_csm.c +++ b/src/iccpd/src/iccp_csm.c @@ -245,6 +245,7 @@ void iccp_csm_transit(struct CSM* csm) int len = -1; struct Msg* msg = NULL; ICCP_CONNECTION_STATE_E prev_state; + char *state_str[] = {"NONEXISTENT", "INITIALIZED", "CAPSENT", "CAPREC", "CONNECTING", "OPERATIONAL"}; if (!csm) return; @@ -254,6 +255,7 @@ void iccp_csm_transit(struct CSM* csm) /* No connection, but have state change? reset it...*/ if (csm->current_state != ICCP_NONEXISTENT && csm->sock_fd <= 0) { + ICCPD_LOG_INFO(__FUNCTION__, "csm %d change state from %s to NONEXISTENT.", csm->mlag_id, state_str[csm->current_state]); csm->current_state = ICCP_NONEXISTENT; iccp_csm_enter_state_nonexistent(csm); return; @@ -332,7 +334,8 @@ void iccp_csm_transit(struct CSM* csm) if (prev_state != csm->current_state || (csm->current_state && msg != NULL)) { - ICCPD_LOG_INFO(__FUNCTION__, "csm %d enter state %d .", csm->mlag_id, csm->current_state); + if (prev_state != csm->current_state) + ICCPD_LOG_INFO(__FUNCTION__, "csm %d change state from %s to %s.", csm->mlag_id, state_str[prev_state], state_str[csm->current_state]); switch (csm->current_state) { diff --git a/src/iccpd/src/mlacp_fsm.c b/src/iccpd/src/mlacp_fsm.c index 46a06c198da1..d40466e6221b 100644 --- a/src/iccpd/src/mlacp_fsm.c +++ b/src/iccpd/src/mlacp_fsm.c @@ -603,6 +603,7 @@ void mlacp_fsm_transit(struct CSM* csm) if ((time(NULL) - csm->warm_reboot_disconn_time) >= WARM_REBOOT_TIMEOUT) { csm->warm_reboot_disconn_time = 0; + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot, reconnection timeout, recover to normal reboot!"); mlacp_peer_disconn_handler(csm); } } @@ -1200,6 +1201,7 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) if ((time(NULL) - csm->peer_warm_reboot_time) >= WARM_REBOOT_TIMEOUT) { csm->peer_warm_reboot_time = 0; + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot timeout, recover to normal reboot!"); } } diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index 0f9e6b4d76e2..c50b94e12e58 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -1271,6 +1271,30 @@ static void mlacp_conn_handler_fdb(struct CSM* csm) return; } +static void mlacp_fix_bridge_mac(struct CSM* csm) +{ + char syscmd[128]; + int ret = 0; + char macaddr[64]; + uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + if (memcmp(MLACP(csm).system_id, null_mac, ETHER_ADDR_LEN) != 0) + { + memset(macaddr, 0, 64); + snprintf(macaddr, 64, "%02x:%02x:%02x:%02x:%02x:%02x", + MLACP(csm).system_id[0], MLACP(csm).system_id[1], MLACP(csm).system_id[2], + MLACP(csm).system_id[3], MLACP(csm).system_id[4], MLACP(csm).system_id[5]); + + /*When changing the mac of a vlan member port, the mac of Bridge will be changed.*/ + /*The Bridge mac can not be the same as peer system id, so fix the Bridge MAC address here.*/ + sprintf(syscmd, "ip link set dev Bridge address %s > /dev/null 2>&1", macaddr); + ret = system(syscmd); + ICCPD_LOG_DEBUG(__FUNCTION__, " %s ret = %d", syscmd, ret); + } + + return; +} + /***************************************** * Peer connect/disconnect handler * @@ -1291,6 +1315,7 @@ void mlacp_peer_conn_handler(struct CSM* csm) { /*If peer reconnected, reset peer disconnect time*/ csm->warm_reboot_disconn_time = 0; + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot and reconnect, reset peer disconnect time!"); } if (csm->peer_link_if) @@ -1302,6 +1327,7 @@ void mlacp_peer_conn_handler(struct CSM* csm) if (first_time == 0) { first_time = 1; + mlacp_fix_bridge_mac(csm); /*If warm reboot, don't flush FDB*/ if (sys->warmboot_start != WARM_REBOOT) mlacp_clean_fdb(); @@ -1399,6 +1425,7 @@ void mlacp_peer_disconn_handler(struct CSM* csm) /*peer connection must be establised again within 90s from last disconnection for peer warm reboot*/ time(&csm->warm_reboot_disconn_time); + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot and disconnect, recover to normal reboot for next time!"); return; } diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c index 3b4bbbb642c8..64eee9b3e4a1 100644 --- a/src/iccpd/src/mlacp_sync_prepare.c +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -600,6 +600,8 @@ int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_siz tlv->icc_parameter.len = htons(sizeof(struct mLACPWarmbootTLV) - sizeof(ICCParameter)); tlv->warmboot = 0x1; + + ICCPD_LOG_DEBUG(__FUNCTION__, "Send warm reboot notification to peer!"); return msg_len; } diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c index 404e2dda6e9b..c177f084e953 100644 --- a/src/iccpd/src/mlacp_sync_update.c +++ b/src/iccpd/src/mlacp_sync_update.c @@ -742,6 +742,7 @@ int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv) return MCLAG_ERROR; time(&csm->peer_warm_reboot_time); + ICCPD_LOG_DEBUG(__FUNCTION__, "Receive warm reboot notification from peer!"); return 0; } diff --git a/src/iccpd/src/port.c b/src/iccpd/src/port.c index c05e3e6eaaa1..3e985981188d 100644 --- a/src/iccpd/src/port.c +++ b/src/iccpd/src/port.c @@ -592,6 +592,9 @@ int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) vlan->vid = vid; vlan->vlan_removed = 0; vlan->vlan_itf = local_if_find_by_name(vlan_name); + + update_if_ipmac_on_standby(local_if); + return 0; } diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c index 557090846bd9..7a62159a8a99 100644 --- a/src/iccpd/src/scheduler.c +++ b/src/iccpd/src/scheduler.c @@ -487,6 +487,7 @@ void session_client_conn_handler(struct CSM *csm) int connFd = -1, connStat = -1; struct timeval con_tv; socklen_t len = sizeof(con_tv); + int err = 0; struct sockaddr_in src_addr; bzero(&(src_addr), sizeof(src_addr)); @@ -522,9 +523,11 @@ void session_client_conn_handler(struct CSM *csm) ICCPD_LOG_INFO(__FUNCTION__, "Set socket timeout fail"); } - if (bind(connFd, (struct sockaddr*)&(src_addr), sizeof(src_addr)) < 0) + err = bind(connFd, (struct sockaddr*)&(src_addr), sizeof(src_addr)); + if (err < 0) { - ICCPD_LOG_INFO(__FUNCTION__, "Bind socket failed. Error"); + ICCPD_LOG_INFO(__FUNCTION__, "Bind socket failed. Error = %d errno = %d ",err,errno); + goto conn_fail; } /* Try conn*/ From 25490d13b1aa6818c2487eb6ea98df3b51f04bbf Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Sun, 15 Sep 2019 23:49:52 -0700 Subject: [PATCH 17/23] optimize some code Signed-off-by: shine.chen --- src/iccpd/include/port.h | 1 + src/iccpd/src/iccp_cli.c | 2 -- src/iccpd/src/iccp_netlink.c | 23 +++++++++++++++++------ src/iccpd/src/mlacp_link_handler.c | 6 +++--- src/iccpd/src/mlacp_sync_update.c | 6 ++++++ 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/iccpd/include/port.h b/src/iccpd/include/port.h index 2da00fef10fe..4faff0676764 100644 --- a/src/iccpd/include/port.h +++ b/src/iccpd/include/port.h @@ -104,6 +104,7 @@ struct LocalInterface uint8_t prefixlen; uint8_t l3_mode; + uint8_t l3_mac_addr[ETHER_ADDR_LEN]; uint8_t is_peer_link; char portchannel_member_buf[512]; uint8_t is_arp_accept; diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c index 0127482125a6..496cdc8e0981 100644 --- a/src/iccpd/src/iccp_cli.c +++ b/src/iccpd/src/iccp_cli.c @@ -465,8 +465,6 @@ int set_local_system_id(const char* mac) { struct System* sys = NULL; struct CSM* csm = NULL; - char syscmd[128]; - int ret = 0; if ((sys = system_get_instance()) == NULL ) return 0; diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c index 59a17cd22e40..c7c58be2b268 100644 --- a/src/iccpd/src/iccp_netlink.c +++ b/src/iccpd/src/iccp_netlink.c @@ -552,7 +552,13 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) memset(macaddr, 0, 64); SET_MAC_STR(macaddr, MLACP(csm).remote_system.system_id); if (local_if_is_l3_mode(lif_po)) - iccp_set_interface_ipadd_mac(lif_po, macaddr ); + { + if (memcmp(lif_po->l3_mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN) != 0) + { + iccp_set_interface_ipadd_mac(lif_po, macaddr ); + memcpy(lif_po->l3_mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); + } + } else { LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) @@ -563,13 +569,17 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) /*If the po is under a vlan, update vlan mac*/ if (local_if_is_l3_mode(vlan->vlan_itf)) { - ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); - if (ret != 0) + if (memcmp(vlan->vlan_itf->l3_mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN) != 0) { - ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", vlan->vlan_itf->name, ret); + ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); + if (ret != 0) + { + ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", vlan->vlan_itf->name, ret); + } + + iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr ); + memcpy(vlan->vlan_itf->l3_mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); } - - iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr ); } } } @@ -835,6 +845,7 @@ int iccp_local_if_addr_update(struct nl_msg *msg, void *arg) lif->ipv4_addr = 0; lif->prefixlen = 0; lif->l3_mode = 0; + memset(lif->l3_mac_addr, 0, ETHER_ADDR_LEN); } len = n->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)); diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index c50b94e12e58..303c02f72c51 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -1302,7 +1302,7 @@ static void mlacp_fix_bridge_mac(struct CSM* csm) void mlacp_peer_conn_handler(struct CSM* csm) { struct LocalInterface *lif = NULL; - static int first_time = 0; + static int once_connected = 0; struct System* sys = NULL; if (!csm) @@ -1324,9 +1324,9 @@ void mlacp_peer_conn_handler(struct CSM* csm) } /*If peer connect again, don't flush FDB*/ - if (first_time == 0) + if (once_connected == 0) { - first_time = 1; + once_connected = 1; mlacp_fix_bridge_mac(csm); /*If warm reboot, don't flush FDB*/ if (sys->warmboot_start != WARM_REBOOT) diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c index c177f084e953..cbbcfc371a1f 100644 --- a/src/iccpd/src/mlacp_sync_update.c +++ b/src/iccpd/src/mlacp_sync_update.c @@ -214,6 +214,12 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * if (strlen(csm->peer_itf_name) != 0) { + if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) + { + /*This MAC is already point to peer-link*/ + return; + } + if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) { /*Redirect the mac to peer-link*/ From 9c81ed1c4cbc2340b303e85924a5541403fdf6e6 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Tue, 17 Sep 2019 22:59:32 -0700 Subject: [PATCH 18/23] fix some bugs for warm-reboot Signed-off-by: shine.chen --- src/iccpd/src/iccp_netlink.c | 4 +++ src/iccpd/src/mlacp_link_handler.c | 55 +++++++++++++++++++----------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c index c7c58be2b268..c201a512d1cc 100644 --- a/src/iccpd/src/iccp_netlink.c +++ b/src/iccpd/src/iccp_netlink.c @@ -628,7 +628,10 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) memset(macaddr, 0, 64); SET_MAC_STR(macaddr, MLACP(csm).system_id); if (local_if_is_l3_mode(lif_po)) + { iccp_set_interface_ipadd_mac(lif_po, macaddr ); + memcpy(lif_po->l3_mac_addr, MLACP(csm).system_id, ETHER_ADDR_LEN); + } else { LIST_FOREACH(vlan, &(lif_po->vlan_list), port_next) @@ -646,6 +649,7 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) } iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr); + memcpy(vlan->vlan_itf->l3_mac_addr, MLACP(csm).system_id, ETHER_ADDR_LEN); } } } diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index 303c02f72c51..09ff85b2120f 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -1256,14 +1256,31 @@ static void mlacp_conn_handler_fdb(struct CSM* csm) /*Wait the ACK from peer?*/ /*mac_msg->age_flag &= ~MAC_AGE_PEER;*/ - /*Send mac add message to peer*/ - mac_msg->op_type = MAC_SYNC_ADD; - if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + /*If MAC with local age flag, dont sync to peer. Such MAC only exist when peer is warm-reboot. + If peer is warm-reboot, peer age flag is not set when connection is lost. + When MAC is aged in local switch, this MAC is not deleted for no peer age flag. + After warm-reboot, this MAC must be learnt by peer and sync to local switch*/ + if (!(mac_msg->age_flag & MAC_AGE_LOCAL)) { - mac_msg->age_flag &= ~MAC_AGE_PEER; - TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + /*Send mac add message to peer*/ + mac_msg->op_type = MAC_SYNC_ADD; + if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0) + { + mac_msg->age_flag &= ~MAC_AGE_PEER; + TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } + } + else + { + /*If MAC with local age flag and is point to MCLAG enabled port, reomove local age flag*/ + if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list not enqueue for local age flag: %s, mac %s vlan-id %d, age_flag %d, remove local age flag", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + mac_msg->age_flag &= ~MAC_AGE_LOCAL; + } } } } @@ -1394,6 +1411,18 @@ void mlacp_peer_disconn_handler(struct CSM* csm) if (sys->warmboot_exit == WARM_REBOOT) return; + /*If peer is warm reboot, don't change FDB*/ + if (csm->peer_warm_reboot_time != 0) + { + /*If peer disconnected, recover peer to normal reboot for next time*/ + csm->peer_warm_reboot_time = 0; + /*peer connection must be establised again within 90s + from last disconnection for peer warm reboot*/ + time(&csm->warm_reboot_disconn_time); + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot and disconnect, recover to normal reboot for next time!"); + return; + } + TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail) { mac_msg = (struct MACMsg*)msg->buf; @@ -1417,18 +1446,6 @@ void mlacp_peer_disconn_handler(struct CSM* csm) free(msg); } - /*If peer is warm reboot, only set peer age flag to MACs*/ - if (csm->peer_warm_reboot_time != 0) - { - /*If peer disconnected, recover peer to normal reboot for next time*/ - csm->peer_warm_reboot_time = 0; - /*peer connection must be establised again within 90s - from last disconnection for peer warm reboot*/ - time(&csm->warm_reboot_disconn_time); - ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot and disconnect, recover to normal reboot for next time!"); - return; - } - /* Clean all port block*/ peerlink_port_isolate_cleanup(csm); From e417140f14b4e9a542c3d4342722f59ed95987ed Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Tue, 24 Sep 2019 19:55:20 -0700 Subject: [PATCH 19/23] refine log level Signed-off-by: shine.chen --- src/iccpd/include/iccp_ifm.h | 2 +- src/iccpd/src/iccp_ifm.c | 63 ++++++++++++++++-------------- src/iccpd/src/iccp_netlink.c | 4 +- src/iccpd/src/mlacp_link_handler.c | 28 +++++++------ src/iccpd/src/mlacp_sync_prepare.c | 8 ++-- src/iccpd/src/mlacp_sync_update.c | 61 +++++++++++++---------------- 6 files changed, 83 insertions(+), 83 deletions(-) diff --git a/src/iccpd/include/iccp_ifm.h b/src/iccpd/include/iccp_ifm.h index 4f99d4cea336..7fbb1a8cf4f9 100644 --- a/src/iccpd/include/iccp_ifm.h +++ b/src/iccpd/include/iccp_ifm.h @@ -30,7 +30,7 @@ int iccp_sys_local_if_list_get_init(); int iccp_arp_get_init(); -void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]); +void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]); int do_one_neigh_request(struct nlmsghdr *n); diff --git a/src/iccpd/src/iccp_ifm.c b/src/iccpd/src/iccp_ifm.c index e8b33b58184a..db4165b1a244 100644 --- a/src/iccpd/src/iccp_ifm.c +++ b/src/iccpd/src/iccp_ifm.c @@ -109,7 +109,7 @@ int iccp_sys_local_if_list_get_init() return ret; } -static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) +static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) { struct System *sys = NULL; struct CSM *csm = NULL; @@ -146,14 +146,14 @@ static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) arp_msg->ipv4_addr = ntohl(arp_msg->ipv4_addr); - ICCPD_LOG_DEBUG(__FUNCTION__, "arp msg type %d , state (%04X)(%d) ifindex [%d] (%s) ip %s , mac [%02X:%02X:%02X:%02X:%02X:%02X] ", - msgtype, ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), + ICCPD_LOG_DEBUG(__FUNCTION__, "arp type %s, state (%04X)(%d) ifindex [%d] (%s) ip %s, mac [%02X:%02X:%02X:%02X:%02X:%02X]", + msgtype == RTM_NEWNEIGH ? "New":"Del", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), ndm->ndm_ifindex, arp_lif->name, show_ip_str(htonl(arp_msg->ipv4_addr)), arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); /*Debug*/ - #if 1 + #if 0 /* dump receive kernel ARP req*/ fprintf(stderr, "\n======== Kernel ARP ==========\n"); fprintf(stderr, " Type = [%d] (New=%d, Del=%d)\n", msgtype, RTM_NEWNEIGH, RTM_DELNEIGH); @@ -188,7 +188,7 @@ static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) if (!vlan_id_list) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from intf %s of vlan %s", lif_po->name, vlan_id_list->vlan_itf->name); } else @@ -197,8 +197,7 @@ static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) if (ndm->ndm_ifindex != lif_po->ifindex) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", - lif_po->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from intf %s", lif_po->name); } verify_arp = 1; @@ -226,7 +225,9 @@ static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) { /* delete ARP*/ TAILQ_REMOVE(&MLACP(csm).arp_list, msg, tail); - free(msg->buf); free(msg); msg = NULL; + free(msg->buf); + free(msg); + msg = NULL; ICCPD_LOG_DEBUG(__FUNCTION__, "Delete ARP %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } @@ -261,9 +262,9 @@ static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len) == 0) { mlacp_enqueue_arp(csm, msg); - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + /*ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", arp_msg->ifname, - show_ip_str(htonl(arp_msg->ipv4_addr))); + show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", @@ -278,11 +279,11 @@ static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", - show_ip_str(htonl(arp_msg->ipv4_addr))); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] message for %s", + show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } @@ -296,18 +297,18 @@ static void do_arp_request(struct ndmsg *ndm, struct rtattr *tb[], int msgtype) if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[DEL] for %s", - show_ip_str(htonl(arp_msg->ipv4_addr))); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[DEL] message for %s", + show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[DEL] for %s", + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[DEL] message for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } } /*Debug: dump for dequeue ARP Info*/ - #if 1 + #if 0 fprintf(stderr, "\n======== ARP Info List ========\n"); TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { @@ -391,7 +392,7 @@ int do_one_neigh_request(struct nlmsghdr *n) if (ndm->ndm_family == AF_INET) { - do_arp_request(ndm, tb, n->nlmsg_type); + do_arp_learn_from_kernel(ndm, tb, n->nlmsg_type); } return(0); @@ -460,7 +461,7 @@ int iccp_arp_get_init() } /*When received ARP packets from kernel, update arp information*/ -void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]) +void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]) { struct System *sys = NULL; struct CSM *csm = NULL; @@ -492,8 +493,12 @@ void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETH memcpy(&arp_msg->ipv4_addr, &addr, 4); memcpy(arp_msg->mac_addr, mac_addr, 6); + ICCPD_LOG_DEBUG(__FUNCTION__, "arp ifindex [%d] (%s) ip %s mac [%02X:%02X:%02X:%02X:%02X:%02X]", + ifindex, arp_lif->name, + show_ip_str(htonl(arp_msg->ipv4_addr)), + arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); /*Debug*/ - #if 1 + #if 0 /* dump receive kernel ARP req*/ fprintf(stderr, "\n======== Kernel ARP Update==========\n"); fprintf(stderr, " Type = (New=%d)\n", RTM_NEWNEIGH); @@ -526,7 +531,7 @@ void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETH if (!vlan_id_list) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s) of vlan (%s)", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from intf %s of vlan %s", lif_po->name, vlan_id_list->vlan_itf->name); } else @@ -534,7 +539,7 @@ void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETH /* Is the ARP belong to a L3 mode MLAG itf?*/ if (ifindex != lif_po->ifindex) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from itf (%s)", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from intf %s", lif_po->name); } @@ -581,14 +586,12 @@ void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETH if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len) == 0) { mlacp_enqueue_arp(csm, msg); - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", - arp_msg->ifname, - show_ip_str(htonl(arp_msg->ipv4_addr))); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", + arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", - arp_msg->ifname, - show_ip_str(htonl(arp_msg->ipv4_addr))); + arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr))); } /* enqueue iccp_msg (add)*/ @@ -598,11 +601,11 @@ void do_arp_update(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETH if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", - show_ip_str(htonl(arp_msg->ipv4_addr))); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c index c201a512d1cc..a4a187716370 100644 --- a/src/iccpd/src/iccp_netlink.c +++ b/src/iccpd/src/iccp_netlink.c @@ -1035,7 +1035,7 @@ int iccp_system_init_netlink_socket() goto err_route_event_sock_connect; } - err = nl_socket_set_buffer_size(sys->route_event_sock, 98304, 0); + err = nl_socket_set_buffer_size(sys->route_event_sock, 983040, 0); if (err) { ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink route event sock."); @@ -1257,7 +1257,7 @@ static int iccp_receive_arp_packet_handler(struct System *sys) memcpy(mac_addr, (char*)(a + 1), ETHER_ADDR_LEN); memcpy(&addr, (char*)(a + 1) + a->ar_hln, 4); - do_arp_update(ifindex, ntohl(addr), mac_addr); + do_arp_update_from_reply_packet(ifindex, ntohl(addr), mac_addr); return 0; } diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index 09ff85b2120f..b2a917d5ae9b 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -105,7 +105,7 @@ int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac) int rc; int sock_fd = 0; - ICCPD_LOG_DEBUG(__FUNCTION__, "Set arp entry for IP:%s MAC:%s ifname:%s\n", show_ip_str(htonl(ip)), mac, ifname); + ICCPD_LOG_DEBUG(__FUNCTION__, "Set arp entry for IP:%s MAC:%s ifname:%s", show_ip_str(htonl(ip)), mac, ifname); if (ifname == NULL || ip == 0 || mac == NULL) { @@ -159,7 +159,7 @@ int mlacp_fsm_arp_del(char *ifname, uint32_t ip) int rc; int sock_fd = 0; - ICCPD_LOG_DEBUG(__FUNCTION__, "%s: Del arp entry for IP : %s\n", __FUNCTION__, show_ip_str(htonl(ip))); + ICCPD_LOG_DEBUG(__FUNCTION__, "Del arp entry for IP : %s ifname:%s", show_ip_str(htonl(ip)), ifname); if (ifname == NULL || ip == 0) { @@ -1031,8 +1031,8 @@ void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg, uint8_t mac_type) mac_info->op_type = mac_msg->op_type; msg_hdr->len = sizeof(struct IccpSyncdHDr) + sizeof(struct mclag_fdb_info); - ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d write mac msg vid : %d ; ifname %s ; mac %s fdb type %d ; op type %d ", - sys->sync_fd, mac_info->vid, mac_info->port_name, mac_info->mac, mac_info->type, mac_info->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "write mac msg vid : %d ; ifname %s ; mac %s fdb type %s ; op type %s", + mac_info->vid, mac_info->port_name, mac_info->mac, mac_info->type == MAC_TYPE_STATIC ? "static" : "dynamic", mac_info->op_type == MAC_SYNC_ADD ? "add" : "del"); /*send msg*/ if (sys->sync_fd > 0 ) @@ -1674,8 +1674,9 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch mac_msg->age_flag = 0; + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC msg vid %d mac %s port %s optype %s ", vid, mac_str, ifname, op_type == MAC_SYNC_ADD ? "add" : "del"); /*Debug*/ - #if 1 + #if 0 /* dump receive MAC info*/ fprintf(stderr, "\n======== MAC Update==========\n"); fprintf(stderr, " MAC = %s\n", mac_str); @@ -1794,8 +1795,8 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch /*set MAC_AGE_PEER flag before send this item to peer*/ mac_msg->age_flag |= MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);*/ mac_msg->op_type = MAC_SYNC_ADD; if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE) @@ -1806,7 +1807,12 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch mac_msg->age_flag &= ~MAC_AGE_PEER; TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + /*ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);*/ + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC-msg-list: %s, add %s vlan-id %d, age_flag %d", mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); } } @@ -1816,8 +1822,8 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch { TAILQ_INSERT_TAIL(&(MLACP(csm).mac_list), msg, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-list enqueue: %s, add %s vlan-id %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-list enqueue: %s, add %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);*/ } else ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC %s, add %s vlan-id %d", @@ -1946,7 +1952,7 @@ int iccp_receive_fdb_handler_from_syncd(struct System *sys) for (i = 0; i < count; i++) { mac_info = (struct mclag_fdb_info *)&msg_buf[pos + sizeof(struct IccpSyncdHDr ) + i * sizeof(struct mclag_fdb_info)]; - ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d vid %d mac %s port %s optype %d ", i, mac_info->vid, mac_info->mac, mac_info->port_name, mac_info->op_type); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "recv msg fdb count %d vid %d mac %s port %s optype %s ", i, mac_info->vid, mac_info->mac, mac_info->port_name, mac_info->op_type == MAC_SYNC_ADD ? "add" : "del");*/ do_mac_update_from_syncd(mac_info->mac, mac_info->vid, mac_info->port_name, mac_info->type, mac_info->op_type); } diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c index 64eee9b3e4a1..fb9ed0aac5fa 100644 --- a/src/iccpd/src/mlacp_sync_prepare.c +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -327,8 +327,7 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu MacData->vid = htons(mac_msg->vid); #if 1 - ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg type = TLV_T_MLACP_MAC_INFO"); - ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s mac = %s, vid = %d, type = %d count %d msg len %d", mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type, count, msg_len); + ICCPD_LOG_DEBUG(__FUNCTION__, "Send MAC messge to peer, port %s mac = %s, vid = %d, type = %s count %d ", mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count); #endif return msg_len; @@ -379,9 +378,8 @@ int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, ArpData->ipv4_addr = htonl(arp_msg->ipv4_addr); memcpy(ArpData->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); - ICCPD_LOG_DEBUG(__FUNCTION__, "Prepare Msg if name %s mac =%02x:%02x:%02x:%02x:%02x:%02x ", ArpData->ifname, ArpData->mac_addr[0], ArpData->mac_addr[1], ArpData->mac_addr[2], - ArpData->mac_addr[3], ArpData->mac_addr[4], ArpData->mac_addr[5]); - ICCPD_LOG_DEBUG(__FUNCTION__, " IP Addr = %s ", show_ip_str( ArpData->ipv4_addr)); + ICCPD_LOG_DEBUG(__FUNCTION__, "Send ARP messge to peer, if name %s mac %02x:%02x:%02x:%02x:%02x:%02x IP %s", ArpData->ifname, ArpData->mac_addr[0], ArpData->mac_addr[1], ArpData->mac_addr[2], + ArpData->mac_addr[3], ArpData->mac_addr[4], ArpData->mac_addr[5], show_ip_str( ArpData->ipv4_addr)); return msg_len; } diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c index cbbcfc371a1f..e98ed9015c5d 100644 --- a/src/iccpd/src/mlacp_sync_update.c +++ b/src/iccpd/src/mlacp_sync_update.c @@ -168,8 +168,8 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * #if 1 ICCPD_LOG_INFO(__FUNCTION__, - "Received MAC Info, itf=[%s] vid[%d] MAC[%s] type %d ", - MacData->ifname, ntohs(MacData->vid), MacData->mac_str, MacData->type); + "Received MAC Info, port[%s] vid[%d] MAC[%s] type[%s]", + MacData->ifname, ntohs(MacData->vid), MacData->mac_str, MacData->type == MAC_SYNC_ADD ? "add" : "del"); #endif /*Find the interface in MCLAG interface list*/ @@ -193,8 +193,8 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * if (MacData->type == MAC_SYNC_ADD) { mac_msg->age_flag &= ~MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d", - mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, add %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); /*mac_msg->fdb_type = tlv->fdb_type;*/ /*The port ifname is different to the local item*/ @@ -298,8 +298,8 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * if (msg && MacData->type == MAC_SYNC_DEL) { mac_msg->age_flag |= MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %d ifname %s, add %s vlan-id %d, op_type %d", - mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %d ifname %s, add %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) { @@ -334,8 +334,8 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * if (strlen(csm->peer_itf_name) == 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "orphan port %d or portchannel is down, but peer-link is not configured: ifname %s, add %s vlan-id %d, op_type %d", - from_mclag_intf, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "From orphan port or portchannel is down, but peer-link is not configured: ifname %s, add %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); /*if orphan port mac but no peerlink, don't keep this mac*/ if (from_mclag_intf == 0) @@ -346,8 +346,8 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * /*Redirect the mac to peer-link*/ memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); - ICCPD_LOG_DEBUG(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, add %s vlan-id %d, op_type %d", - mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, add %s vlan-id %d", + mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); } } else @@ -450,9 +450,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) #if 1 ICCPD_LOG_INFO(__FUNCTION__, - "%s: Received ARP Info," - "itf=[%s] ARP IP[%s],MAC[%02x:%02x:%02x:%02x:%02x:%02x]", - __FUNCTION__, + "Received ARP Info, intf[%s] IP[%s], MAC[%02x:%02x:%02x:%02x:%02x:%02x]", arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2], arp_entry->mac_addr[3], arp_entry->mac_addr[4], arp_entry->mac_addr[5]); @@ -478,9 +476,8 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) continue; ICCPD_LOG_DEBUG(__FUNCTION__, - "%s: ==> Find ARP itf on L3 bridge, peer-link %s of %s", - __FUNCTION__, - peer_link_if->name, vlan_id_list->vlan_itf->name); + "ARP is learnt from intf %s, peer-link %s is the member of this vlan", + vlan_id_list->vlan_itf->name, peer_link_if->name); /* Peer-link belong to L3 vlan is alive, set the ARP info*/ set_arp_flag = 1; @@ -509,9 +506,8 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) continue; ICCPD_LOG_DEBUG(__FUNCTION__, - "%s: ==> Find ARP itf on L3 bridge, %s of %s", - __FUNCTION__, - local_if->name, vlan_id_list->vlan_itf->name); + "ARP is learnt from intf %s, mclag %s is the member of this vlan", + vlan_id_list->vlan_itf->name, local_if->name); break; } @@ -528,8 +524,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) if (strcmp(local_if->name, arp_entry->ifname) == 0) { ICCPD_LOG_DEBUG(__FUNCTION__, - "%s: ==> Find ARP itf on L3 port-channel, %s", - __FUNCTION__, + "ARP is learnt from mclag L3 intf %s", local_if->name); if (local_if->po_active == 1) { @@ -554,8 +549,8 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) { if (mlacp_fsm_arp_set(arp_entry->ifname, ntohl(arp_entry->ipv4_addr), mac_str) < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP set for %s %s %s", - __FUNCTION__, arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP add failure for %s %s %s", + arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); return MCLAG_ERROR; } } @@ -563,19 +558,18 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) { if (mlacp_fsm_arp_del(arp_entry->ifname, ntohl(arp_entry->ipv4_addr)) < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP delete for %s %s %s", - __FUNCTION__, arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP delete failure for %s %s %s", + arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); return MCLAG_ERROR; } } - ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP update for %s %s %s", - __FUNCTION__, arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ARP update for %s %s %s", + __FUNCTION__, arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str);*/ } else { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s: ==> port-channel is not alive", - __FUNCTION__); + ICCPD_LOG_DEBUG(__FUNCTION__, "Failure: port-channel is not alive"); /*TODO Set static route through peer-link or just skip it?*/ } @@ -596,9 +590,9 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) if (msg && arp_entry->op_type == ARP_SYNC_DEL) { TAILQ_REMOVE(&(MLACP(csm).arp_list), msg, tail); - free(msg->buf); free(msg); - ICCPD_LOG_INFO(__FUNCTION__, "%s: del arp queue successfully", - __FUNCTION__); + free(msg->buf); + free(msg); + /*ICCPD_LOG_INFO(__FUNCTION__, "Del arp queue successfully");*/ } else if (!msg && arp_entry->op_type == ARP_SYNC_ADD) { @@ -610,8 +604,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) if (iccp_csm_init_msg(&msg, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) { mlacp_enqueue_arp(csm, msg); - ICCPD_LOG_INFO(__FUNCTION__, "%s: add arp queue successfully", - __FUNCTION__); + /*ICCPD_LOG_INFO(__FUNCTION__, "Add arp queue successfully");*/ } } From 48b8c5303c93120d968abeb5d106c9344d1b6a13 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Tue, 22 Oct 2019 06:07:04 -0700 Subject: [PATCH 20/23] refine iccpd syslog & skip arp packet whose src ip is local ip Signed-off-by: shine.chen --- src/iccpd/include/iccp_netlink.h | 1 + src/iccpd/include/logger.h | 13 +- src/iccpd/include/port.h | 2 - src/iccpd/src/app_csm.c | 8 +- src/iccpd/src/iccp_cli.c | 10 +- src/iccpd/src/iccp_cmd_show.c | 5 - src/iccpd/src/iccp_consistency_check.c | 2 +- src/iccpd/src/iccp_csm.c | 9 +- src/iccpd/src/iccp_ifm.c | 59 +++++---- src/iccpd/src/iccp_netlink.c | 169 ++++++++++++++++++------- src/iccpd/src/logger.c | 24 +++- src/iccpd/src/mclagdctl/mclagdctl.c | 98 ++++++++++++-- src/iccpd/src/mclagdctl/mclagdctl.h | 15 +++ src/iccpd/src/mlacp_fsm.c | 18 +-- src/iccpd/src/mlacp_link_handler.c | 154 +++++++++++++--------- src/iccpd/src/mlacp_sync_prepare.c | 12 +- src/iccpd/src/mlacp_sync_update.c | 56 ++++---- src/iccpd/src/port.c | 107 +++------------- src/iccpd/src/scheduler.c | 24 ++-- src/iccpd/src/system.c | 1 + 20 files changed, 449 insertions(+), 338 deletions(-) diff --git a/src/iccpd/include/iccp_netlink.h b/src/iccpd/include/iccp_netlink.h index 26ce050b4e48..612a1859591b 100644 --- a/src/iccpd/include/iccp_netlink.h +++ b/src/iccpd/include/iccp_netlink.h @@ -41,6 +41,7 @@ int iccp_init_netlink_event_fd(struct System *sys); int iccp_handle_events(struct System * sys); void update_if_ipmac_on_standby(struct LocalInterface* lif_po); int iccp_sys_local_if_list_get_addr(); +int iccp_check_if_addr_from_netlink(int family, uint8_t *addr, struct LocalInterface *lif); #endif diff --git a/src/iccpd/include/logger.h b/src/iccpd/include/logger.h index 8d4502e8a75e..d21e38d3727d 100644 --- a/src/iccpd/include/logger.h +++ b/src/iccpd/include/logger.h @@ -31,12 +31,12 @@ typedef enum _iccpd_log_level_t { - DEBUG_LOG_LEVEL = 0, - INFO_LOG_LEVEL = 1, - NOTICE_LOG_LEVEL = 2, - WARN_LOG_LEVEL = 3, - ERR_LOG_LEVEL = 4, - CRITICAL_LOG_LEVEL = 5 + CRITICAL_LOG_LEVEL = 0, + ERR_LOG_LEVEL = 1, + WARN_LOG_LEVEL = 2, + NOTICE_LOG_LEVEL = 3, + INFO_LOG_LEVEL = 4, + DEBUG_LOG_LEVEL = 5 } _iccpd_log_level_t; @@ -58,6 +58,7 @@ struct LoggerConfig }; struct LoggerConfig* logger_get_configuration(); +void logger_set_configuration(int log_level); void log_setup(char* progname, char* path); void log_finalize(); void log_init(struct CmdOptionParser* parser); diff --git a/src/iccpd/include/port.h b/src/iccpd/include/port.h index 4faff0676764..bdcaf66a68ad 100644 --- a/src/iccpd/include/port.h +++ b/src/iccpd/include/port.h @@ -139,8 +139,6 @@ int local_if_is_l3_mode(struct LocalInterface* local_if); void local_if_init(struct LocalInterface*); void local_if_finalize(struct LocalInterface*); -void ether_mac_set_addr_with_if_name(char* name, uint8_t* mac); - struct PeerInterface* peer_if_create(struct CSM* csm, int peer_if_number, int type); struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name); diff --git a/src/iccpd/src/app_csm.c b/src/iccpd/src/app_csm.c index 6588587bd8ec..589cf94015d8 100644 --- a/src/iccpd/src/app_csm.c +++ b/src/iccpd/src/app_csm.c @@ -249,9 +249,7 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif) lif_po = local_if_find_by_po_id(lif->po_id); if (lif_po == NULL) { - ICCPD_LOG_WARN(__FUNCTION__, - "Failed to find port_channel instance for %d.", - lif->po_id); + ICCPD_LOG_WARN(__FUNCTION__, "Failed to find port_channel instance for %d.", lif->po_id); return MCLAG_ERROR; } @@ -305,9 +303,7 @@ int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname) } else { - ICCPD_LOG_WARN(__FUNCTION__, - "%s: Failed to find a port instance .", - ifname); + ICCPD_LOG_WARN(__FUNCTION__, "%s: Failed to find a port instance .", ifname); return 0; } /* process link state handler after attaching it.*/ diff --git a/src/iccpd/src/iccp_cli.c b/src/iccpd/src/iccp_cli.c index 496cdc8e0981..8d0ede8b3feb 100644 --- a/src/iccpd/src/iccp_cli.c +++ b/src/iccpd/src/iccp_cli.c @@ -293,15 +293,14 @@ int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, - "attach interface(%s) is not a port-channel", ifname); + ICCPD_LOG_WARN(__FUNCTION__, "Attach interface(%s) is not a port-channel", ifname); return MCLAG_ERROR; } csm = system_get_csm_by_mlacp_id(domain); if (csm == NULL) { - ICCPD_LOG_DEBUG(__FUNCTION__, "MC-LAG ID %d doesn't exist", domain); + ICCPD_LOG_WARN(__FUNCTION__, "MC-LAG ID %d doesn't exist", domain); return MCLAG_ERROR; } @@ -343,8 +342,7 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) if (strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, - "detach interface(%s) is not a port-channel", ifname); + ICCPD_LOG_WARN(__FUNCTION__, "Detach interface(%s) is not a port-channel", ifname); return MCLAG_ERROR; } @@ -360,7 +358,7 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname) /* find csm*/ csm = lif_po->csm; - ICCPD_LOG_DEBUG(__FUNCTION__, "detach mclag id = %d from ifname = %s", + ICCPD_LOG_DEBUG(__FUNCTION__, "Detach mclag id = %d from ifname = %s", csm->mlag_id, lif_po->name); /* process link state handler before detaching it.*/ diff --git a/src/iccpd/src/iccp_cmd_show.c b/src/iccpd/src/iccp_cmd_show.c index ee01fe9a6629..5b42de54bbb9 100644 --- a/src/iccpd/src/iccp_cmd_show.c +++ b/src/iccpd/src/iccp_cmd_show.c @@ -50,7 +50,6 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) if (!(sys = system_get_instance())) { - ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); return EXEC_TYPE_NO_EXIST_SYS; } @@ -150,7 +149,6 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id) if (!(sys = system_get_instance())) { - ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); return EXEC_TYPE_NO_EXIST_SYS; } @@ -216,7 +214,6 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id) if (!(sys = system_get_instance())) { - ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); return EXEC_TYPE_NO_EXIST_SYS; } @@ -288,7 +285,6 @@ int iccp_local_if_dump(char * *buf, int *num, int mclag_id) if (!(sys = system_get_instance())) { - ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); return EXEC_TYPE_NO_EXIST_SYS; } @@ -406,7 +402,6 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id) if (!(sys = system_get_instance())) { - ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n"); return EXEC_TYPE_NO_EXIST_SYS; } diff --git a/src/iccpd/src/iccp_consistency_check.c b/src/iccpd/src/iccp_consistency_check.c index b48e4eb37a96..90ac9cd9e790 100644 --- a/src/iccpd/src/iccp_consistency_check.c +++ b/src/iccpd/src/iccp_consistency_check.c @@ -165,7 +165,7 @@ enum Reason_ID iccp_consistency_check(char* ifname) ret = check_func[i](ifname); if (ret != 1) { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s ret = %d", reasons[i], ret); + ICCPD_LOG_WARN(__FUNCTION__, "%s ret = %d", reasons[i], ret); fprintf(stdout, "%s \n", reasons[i]); return i; } diff --git a/src/iccpd/src/iccp_csm.c b/src/iccpd/src/iccp_csm.c index e95aa7fa158e..79e17b9e1ba2 100644 --- a/src/iccpd/src/iccp_csm.c +++ b/src/iccpd/src/iccp_csm.c @@ -255,15 +255,12 @@ void iccp_csm_transit(struct CSM* csm) /* No connection, but have state change? reset it...*/ if (csm->current_state != ICCP_NONEXISTENT && csm->sock_fd <= 0) { - ICCPD_LOG_INFO(__FUNCTION__, "csm %d change state from %s to NONEXISTENT.", csm->mlag_id, state_str[csm->current_state]); + ICCPD_LOG_NOTICE(__FUNCTION__, "csm %d change state from %s to NONEXISTENT.", csm->mlag_id, state_str[csm->current_state]); csm->current_state = ICCP_NONEXISTENT; iccp_csm_enter_state_nonexistent(csm); return; } - /*if (csm->current_state != ICCP_NONEXISTENT) - ICCPD_LOG_DEBUG(__FUNCTION__, "#Begin# id:%d, fd:%d, ICCP CSM State:%d", csm->mlag_id, csm->sock_fd, csm->current_state);*/ - msg = iccp_csm_dequeue_msg(csm); switch (csm->current_state) @@ -335,7 +332,7 @@ void iccp_csm_transit(struct CSM* csm) if (prev_state != csm->current_state || (csm->current_state && msg != NULL)) { if (prev_state != csm->current_state) - ICCPD_LOG_INFO(__FUNCTION__, "csm %d change state from %s to %s.", csm->mlag_id, state_str[prev_state], state_str[csm->current_state]); + ICCPD_LOG_NOTICE(__FUNCTION__, "csm %d change state from %s to %s.", csm->mlag_id, state_str[prev_state], state_str[csm->current_state]); switch (csm->current_state) { @@ -367,8 +364,6 @@ void iccp_csm_transit(struct CSM* csm) break; } } - /*if (csm->current_state != ICCP_NONEXISTENT && prev_state != csm->current_state) - ICCPD_LOG_DEBUG(__FUNCTION__, "#End# id:%d, fd:%d, ICCP CSM State:%d", csm->mlag_id, csm->sock_fd, csm->current_state);*/ } /* Set up ICCP message */ diff --git a/src/iccpd/src/iccp_ifm.c b/src/iccpd/src/iccp_ifm.c index db4165b1a244..cf874366b97b 100644 --- a/src/iccpd/src/iccp_ifm.c +++ b/src/iccpd/src/iccp_ifm.c @@ -146,7 +146,7 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int arp_msg->ipv4_addr = ntohl(arp_msg->ipv4_addr); - ICCPD_LOG_DEBUG(__FUNCTION__, "arp type %s, state (%04X)(%d) ifindex [%d] (%s) ip %s, mac [%02X:%02X:%02X:%02X:%02X:%02X]", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP type %s, state (%04X)(%d) ifindex [%d] (%s) ip %s, mac [%02X:%02X:%02X:%02X:%02X:%02X]", msgtype == RTM_NEWNEIGH ? "New":"Del", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state), ndm->ndm_ifindex, arp_lif->name, show_ip_str(htonl(arp_msg->ipv4_addr)), @@ -188,8 +188,8 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int if (!vlan_id_list) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from intf %s of vlan %s", - lif_po->name, vlan_id_list->vlan_itf->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from mclag enabled member port of vlan %s", + vlan_id_list->vlan_itf->name); } else { @@ -197,7 +197,7 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int if (ndm->ndm_ifindex != lif_po->ifindex) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from intf %s", lif_po->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from mclag enabled intf %s", lif_po->name); } verify_arp = 1; @@ -228,8 +228,7 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int free(msg->buf); free(msg); msg = NULL; - ICCPD_LOG_DEBUG(__FUNCTION__, "Delete ARP %s", - show_ip_str(htonl(arp_msg->ipv4_addr))); + ICCPD_LOG_DEBUG(__FUNCTION__, "Delete ARP %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } else { @@ -243,8 +242,7 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int arp_info->op_type = arp_msg->op_type; sprintf(arp_info->ifname, "%s", arp_msg->ifname); memcpy(arp_info->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); - ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", - show_ip_str(htonl(arp_msg->ipv4_addr))); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } } break; @@ -263,13 +261,11 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int { mlacp_enqueue_arp(csm, msg); /*ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s", - arp_msg->ifname, - show_ip_str(htonl(arp_msg->ipv4_addr)));*/ + arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", - arp_msg->ifname, - show_ip_str(htonl(arp_msg->ipv4_addr))); + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr))); } /* enqueue iccp_msg (add)*/ @@ -283,7 +279,7 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s", + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } @@ -301,7 +297,7 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[DEL] message for %s", + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[DEL] message for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } @@ -376,11 +372,12 @@ int do_one_neigh_request(struct nlmsghdr *n) ifm_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len); - if (ndm->ndm_state == NUD_INCOMPLETE + if (n->nlmsg_type == RTM_NEWNEIGH + && (ndm->ndm_state == NUD_INCOMPLETE || ndm->ndm_state == NUD_FAILED || ndm->ndm_state == NUD_NOARP || ndm->ndm_state == NUD_PERMANENT - || ndm->ndm_state == NUD_NONE) + || ndm->ndm_state == NUD_NONE)) { return(0); } @@ -430,7 +427,7 @@ int iccp_arp_get_init() &rt_hdr, sizeof(rt_hdr)); if (ret < 0) { - ICCPD_LOG_ERR(__FUNCTION__, "send netlink msg error."); + ICCPD_LOG_ERR(__FUNCTION__, "Send netlink msg error."); return ret; } @@ -449,7 +446,7 @@ int iccp_arp_get_init() nl_cb_put(cb); if (ret < 0) { - ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error."); + ICCPD_LOG_ERR(__FUNCTION__, "Receive netlink msg error."); if (ret != -NLE_DUMP_INTR) return ret; @@ -493,7 +490,7 @@ void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, ui memcpy(&arp_msg->ipv4_addr, &addr, 4); memcpy(arp_msg->mac_addr, mac_addr, 6); - ICCPD_LOG_DEBUG(__FUNCTION__, "arp ifindex [%d] (%s) ip %s mac [%02X:%02X:%02X:%02X:%02X:%02X]", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP ifindex [%d] (%s) ip %s mac [%02X:%02X:%02X:%02X:%02X:%02X]", ifindex, arp_lif->name, show_ip_str(htonl(arp_msg->ipv4_addr)), arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); @@ -531,16 +528,15 @@ void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, ui if (!vlan_id_list) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from intf %s of vlan %s", - lif_po->name, vlan_id_list->vlan_itf->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from mclag enabled port %s of vlan %s", + lif_po->name, vlan_id_list->vlan_itf->name); } else { /* Is the ARP belong to a L3 mode MLAG itf?*/ if (ifindex != lif_po->ifindex) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from intf %s", - lif_po->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is from mclag enabled intf %s", lif_po->name); } verify_arp = 1; @@ -557,6 +553,13 @@ void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, ui if (!verify_arp) return; + if (iccp_check_if_addr_from_netlink(AF_INET, &addr, arp_lif)) + { + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP %s is identical with the ip address of interface %s", + show_ip_str(htonl(arp_msg->ipv4_addr)), arp_lif->name); + return; + } + /* update lif ARP*/ TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail) { @@ -590,7 +593,7 @@ void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, ui arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s", arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr))); } @@ -605,7 +608,7 @@ void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, ui show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s", + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } @@ -713,7 +716,7 @@ void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n) /* if AF_SPEC isn't there, vlan table is not preset for this port */ if (!tb[IFLA_AF_SPEC]) { - ICCPD_LOG_WARN(__FUNCTION__, "%d None\n", (ifm->ifi_index)); + ICCPD_LOG_WARN(__FUNCTION__, "Vlan table is not preset for %d", ifm->ifi_index); return; } else @@ -745,7 +748,7 @@ void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n) { if (vlan->vlan_removed == 1) { - ICCPD_LOG_DEBUG(__FUNCTION__, "Delete VLAN ID = %d from %s", vlan->vid, lif->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", lif->name, vlan->vid); LIST_REMOVE(vlan, port_next); free(vlan); diff --git a/src/iccpd/src/iccp_netlink.c b/src/iccpd/src/iccp_netlink.c index a4a187716370..ec8971d0ceee 100644 --- a/src/iccpd/src/iccp_netlink.c +++ b/src/iccpd/src/iccp_netlink.c @@ -491,7 +491,7 @@ void iccp_set_interface_ipadd_mac(struct LocalInterface *lif, char * mac_addr ) dst_len = strlen(mac_addr); memcpy(sub_msg->data, mac_addr, dst_len); - ICCPD_LOG_DEBUG(__FUNCTION__, "lif name %s address %s mac msg data %s %d \n", lif->name, show_ip_str(htonl(lif->ipv4_addr)), sub_msg->data, dst_len); + ICCPD_LOG_DEBUG(__FUNCTION__, "If name %s ip %s mac %s", lif->name, show_ip_str(htonl(lif->ipv4_addr)), sub_msg->data); sub_msg->op_len = dst_len; msg_hdr->len += sizeof(mclag_sub_option_hdr_t); @@ -536,15 +536,15 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) memcpy(lif_po->mac_addr_ori, lif_po->mac_addr, ETHER_ADDR_LEN); ICCPD_LOG_DEBUG(__FUNCTION__, - "%s Change the system-id of po%d from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", + "%s Change the system-id of %s from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", (csm->role_type == STP_ROLE_STANDBY) ? "Standby" : "Active", - lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], + lif_po->name, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], MLACP(csm).remote_system.system_id[0], MLACP(csm).remote_system.system_id[1], MLACP(csm).remote_system.system_id[2], MLACP(csm).remote_system.system_id[3], MLACP(csm).remote_system.system_id[4], MLACP(csm).remote_system.system_id[5]); ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); if (ret != 0) { - ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", lif_po->name, ret); + ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", lif_po->name, ret); } } @@ -574,7 +574,7 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po) ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN); if (ret != 0) { - ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", vlan->vlan_itf->name, ret); + ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", vlan->vlan_itf->name, ret); } iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr ); @@ -612,15 +612,15 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) if (memcmp( lif_po->mac_addr, MLACP(csm).system_id, ETHER_ADDR_LEN) != 0) { ICCPD_LOG_DEBUG(__FUNCTION__, - "%s Recover the system-id of po%d from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", + "%s Recover the system-id of %s from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].", (csm->role_type == STP_ROLE_STANDBY) ? "Standby" : "Active", - lif_po->po_id, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], + lif_po->name, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5], MLACP(csm).system_id[0], MLACP(csm).system_id[1], MLACP(csm).system_id[2], MLACP(csm).system_id[3], MLACP(csm).system_id[4], MLACP(csm).system_id[5]); ret = iccp_netlink_if_hwaddr_set(lif_po->ifindex, MLACP(csm).system_id, ETHER_ADDR_LEN); if (ret != 0) { - ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", lif_po->name, ret); + ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", lif_po->name, ret); } } @@ -645,7 +645,7 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) ret = iccp_netlink_if_hwaddr_set(vlan->vlan_itf->ifindex, MLACP(csm).system_id, ETHER_ADDR_LEN); if (ret != 0) { - ICCPD_LOG_ERR(__FUNCTION__, " set %s mac error, ret = %d", vlan->vlan_itf->name, ret); + ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", vlan->vlan_itf->name, ret); } iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr); @@ -657,39 +657,6 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po) return; } -void update_local_system_id(struct LocalInterface* local_if) -{ - struct System* sys = NULL; - struct CSM* csm = NULL; - - if ((sys = system_get_instance()) == NULL) - { - ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); - return; - } - - if (local_if->type != IF_T_PORT_CHANNEL) - return; - - /* traverse all CSM */ - LIST_FOREACH(csm, &(sys->csm_list), next) - { - /* sync system info from one port-channel device*/ - if (memcmp(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN) != 0) - { - memcpy(MLACP(csm).system_id, local_if->mac_addr, ETHER_ADDR_LEN); - MLACP(csm).system_config_changed = 1; - - update_if_ipmac_on_standby(local_if); - ICCPD_LOG_INFO(__FUNCTION__, - "update csm %d local system id to mac %02x:%02x:%02x:%02x:%02x:%02x of %s ", csm->mlag_id, local_if->mac_addr[0], local_if->mac_addr[1], - local_if->mac_addr[2], local_if->mac_addr[3], local_if->mac_addr[4], local_if->mac_addr[5], local_if->name ); - } - } - - return; -} - void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) { struct rtnl_link *link; @@ -777,7 +744,7 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) { lif->state = PORT_STATE_UP; /*if(lif->type ==IF_T_PORT_CHANNEL)*/ - ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state up", ifname); + ICCPD_LOG_NOTICE(__FUNCTION__, "Update local port %s state up", ifname); iccp_from_netlink_port_state_handler(lif->name, lif->state); } @@ -785,7 +752,7 @@ void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg) { lif->state = PORT_STATE_DOWN; /*if(lif->type ==IF_T_PORT_CHANNEL)*/ - ICCPD_LOG_INFO(__FUNCTION__, "update local port %s state down", ifname); + ICCPD_LOG_NOTICE(__FUNCTION__, "Update local port %s state down", ifname); iccp_from_netlink_port_state_handler(lif->name, lif->state); } @@ -822,6 +789,110 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg) return; } +int iccp_check_if_addr_from_netlink(int family, uint8_t *addr, struct LocalInterface *lif) +{ + struct + { + struct nlmsghdr nlh; + struct ifaddrmsg ifa; + } req; + + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + + int fd; + struct System *sys; + if ((sys = system_get_instance()) == NULL) + { + return 0; + } + + memset(&req, 0, sizeof(req)); + req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + req.nlh.nlmsg_type = RTM_GETADDR; + req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = 0; + req.ifa.ifa_family = family; + + fd = nl_socket_get_fd(sys->route_sock); + send(fd, (void*)&req, sizeof(req), 0); + + char * buf = malloc(10000); + iov.iov_base = buf; + + while (1) + { + int status; + int msglen = 0; + iov.iov_len = 10000; + status = recvmsg(fd, &msg, 0); + + if (status < 0 || status == 0) + { + ICCPD_LOG_WARN(__FUNCTION__, "netlink receive error (%d) status %d %d ", fd, status, errno); + free(buf); + return 0; + } + struct nlmsghdr *n = (struct nlmsghdr*)buf; + msglen = status; + + while (NLMSG_OK(n, msglen)) + { + if (n->nlmsg_type != RTM_NEWADDR) + { + free(buf); + return 0; + } + struct ifaddrmsg *ifa; + ifa = NLMSG_DATA(n); + if (lif && lif->ifindex == ifa->ifa_index) + { + struct rtattr *rth = IFA_RTA(ifa); + int rtl = IFA_PAYLOAD(n); + + while (rtl && RTA_OK(rth, rtl)) + { + if (rth->rta_type == IFA_ADDRESS || rth->rta_type == IFA_LOCAL) + { + if (family == AF_INET && ifa->ifa_family == AF_INET) + { + if (*(uint32_t *)addr == ntohl(*((uint32_t *)RTA_DATA(rth)))) + { + free(buf); + return 1; + } + } + + if (family == AF_INET6 && ifa->ifa_family == AF_INET6) + { + void *addr_netlink; + addr_netlink = RTA_DATA(rth); + if (!memcmp((uint8_t *)addr_netlink, addr, 16)) + { + free(buf); + return 1; + } + } + } + rth = RTA_NEXT(rth, rtl); + } + } + n = NLMSG_NEXT(n, msglen); + } + } + + free(buf); + + return 0; +} + int iccp_local_if_addr_update(struct nl_msg *msg, void *arg) { int len; @@ -869,7 +940,7 @@ int iccp_local_if_addr_update(struct nl_msg *msg, void *arg) lif->l3_mode = 1; lif->port_config_sync = 1; update_if_ipmac_on_standby(lif); - ICCPD_LOG_DEBUG(__FUNCTION__, " if name %s index %d address %s \n", lif->name, lif->ifindex, show_ip_str(htonl(lif->ipv4_addr))); + ICCPD_LOG_DEBUG(__FUNCTION__, "If name %s index %d ip %s", lif->name, lif->ifindex, show_ip_str(htonl(lif->ipv4_addr))); } rth = RTA_NEXT(rth, rtl); } @@ -917,7 +988,7 @@ int iccp_sys_local_if_list_get_addr() nl_cb_put(cb); if (ret < 0) { - ICCPD_LOG_ERR(__FUNCTION__, "receive netlink msg error ret = %d errno = %d .", ret, errno); + ICCPD_LOG_ERR(__FUNCTION__, "Receive netlink msg error, ret = %d errno = %d .", ret, errno); if (ret != -NLE_DUMP_INTR) return ret; retry = 1; @@ -936,13 +1007,13 @@ static int iccp_route_event_handler(struct nl_msg *msg, void *arg) { case RTM_NEWLINK: if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newlink, &event) < 0) - ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type. "); + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type(RTM_NEWLINK)"); iccp_parse_if_vlan_info_from_netlink(nlh); break; case RTM_DELLINK: if (nl_msg_parse(msg, &iccp_event_handler_obj_input_dellink, NULL) < 0) - ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type."); + ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type(RTM_DELLINK)"); break; case RTM_NEWNEIGH: @@ -1239,7 +1310,7 @@ static int iccp_receive_arp_packet_handler(struct System *sys) (struct sockaddr*)&sll, &sll_len); if (n < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "arp recvfrom: %s", buf); + ICCPD_LOG_WARN(__FUNCTION__, "ARP recvfrom error: %s", buf); return MCLAG_ERROR; } diff --git a/src/iccpd/src/logger.c b/src/iccpd/src/logger.c index c2730093346e..49c3a11393a8 100644 --- a/src/iccpd/src/logger.c +++ b/src/iccpd/src/logger.c @@ -30,12 +30,12 @@ static uint32_t _iccpd_log_level_map[] = { - LOG_DEBUG, - LOG_INFO, - LOG_NOTICE, - LOG_WARNING, - LOG_ERR, LOG_CRIT, + LOG_ERR, + LOG_WARNING, + LOG_NOTICE, + LOG_INFO, + LOG_DEBUG, }; static char* log_level_to_string(int level) @@ -71,13 +71,23 @@ struct LoggerConfig* logger_get_configuration() if (config.init == 0) { config.console_log_enabled = 0; - config.log_level = DEBUG_LOG_LEVEL; + config.log_level = NOTICE_LOG_LEVEL; config.init = 1; } return &config; } +void logger_set_configuration(int log_level) +{ + struct LoggerConfig* config = logger_get_configuration(); + + config->log_level = log_level; + config->init = 1; + + return; +} + void log_init(struct CmdOptionParser* parser) { struct LoggerConfig* config = logger_get_configuration(); @@ -104,7 +114,7 @@ void write_log(const int level, const char* tag, const char* format, ...) return; #endif - if (level < config->log_level) + if (level > config->log_level) return; prefix_len = snprintf(buf, LOGBUF_SIZE, "[%s.%s] ", tag, log_level_to_string(level)); diff --git a/src/iccpd/src/mclagdctl/mclagdctl.c b/src/iccpd/src/mclagdctl/mclagdctl.c index e2d098cf429f..0396f5fa0a7a 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.c +++ b/src/iccpd/src/mclagdctl/mclagdctl.c @@ -94,6 +94,20 @@ static struct command_type command_types[] = .enca_msg = mclagdctl_enca_dump_peer_portlist, .parse_msg = mclagdctl_parse_dump_peer_portlist, }, + { + .id = ID_CMDTYPE_C, + .name = "config", + .enca_msg = NULL, + .parse_msg = NULL, + }, + { + .id = ID_CMDTYPE_C_L, + .parent_id = ID_CMDTYPE_C, + .info_type = INFO_TYPE_CONFIG_LOGLEVEL, + .name = "loglevel", + .enca_msg = mclagdctl_enca_config_loglevel, + .parse_msg = mclagdctl_parse_config_loglevel, + }, }; #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -509,6 +523,31 @@ int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len) return 0; } +int mclagdctl_enca_config_loglevel(char *msg, int log_level, int argc, char **argv) +{ + struct mclagdctl_req_hdr req; + + memset(&req, 0, sizeof(struct mclagdctl_req_hdr)); + req.info_type = INFO_TYPE_CONFIG_LOGLEVEL; + req.mclag_id = log_level; + memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr)); + + return 1; +} + +int mclagdctl_parse_config_loglevel(char *msg, int data_len) +{ + + int ret = *(int*)msg; + + if (ret == 0) + fprintf(stdout, "%s\n", "Set mclag config debug level success!"); + else + fprintf(stdout, "%s\n", "Set mclag config debug level failed!"); + + return 0; +} + static bool __mclagdctl_cmd_executable(struct command_type *cmd_type) { if (!cmd_type->enca_msg || !cmd_type->parse_msg) @@ -625,7 +664,8 @@ static void mclagdctl_print_help(const char *argv0) fprintf(stdout, "%s [options] command [command args]\n" " -h --help Show this help\n" - " -i --mclag-id Specify one mclag id\n", + " -i --mclag-id Specify one mclag id\n" + " -l --level Specify log level critical,err,warn,notice,info,debug\n", argv0); fprintf(stdout, "Commands:\n"); @@ -651,20 +691,22 @@ int main(int argc, char **argv) char *rcv_buf = NULL; static const struct option long_options[] = { - { "help", no_argument, NULL, 'h' }, - { "mclag id", required_argument, NULL, 'i' }, - { NULL, 0, NULL, 0 } + { "help", no_argument, NULL, 'h' }, + { "mclag id", required_argument, NULL, 'i' }, + { "log level", required_argument, NULL, 'l' }, + { NULL, 0, NULL, 0 } }; int opt; int err; struct command_type *cmd_type; int ret; - unsigned mclag_id = 0; + unsigned para_int = 0; + int len = 0; char *data; struct mclagd_reply_hdr *reply; - while ((opt = getopt_long(argc, argv, "hi:", long_options, NULL)) >= 0) + while ((opt = getopt_long(argc, argv, "hil:", long_options, NULL)) >= 0) { switch (opt) { @@ -672,9 +714,43 @@ int main(int argc, char **argv) mclagdctl_print_help(argv0); return EXIT_SUCCESS; - case 'i': - mclag_id = atoi(optarg); - break; + case 'i': + para_int = atoi(optarg); + break; + + case 'l': + switch (tolower(optarg[0])) + { + case 'c': + para_int = CRITICAL; + break; + + case 'e': + para_int = ERR; + break; + + case 'w': + para_int = WARN; + break; + + case 'n': + para_int = NOTICE; + break; + + case 'i': + para_int = INFO; + break; + + case 'd': + para_int = DEBUG; + break; + + default: + fprintf(stderr, "unknown option \"%c\".\n", opt); + mclagdctl_print_help(argv0); + return EXIT_FAILURE; + } + break; case '?': fprintf(stderr, "unknown option.\n"); @@ -712,7 +788,7 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - if (cmd_type->enca_msg(buf, mclag_id, argc, argv) < 0) + if (cmd_type->enca_msg(buf, para_int, argc, argv) < 0) { ret = EXIT_FAILURE; goto mclagdctl_disconnect; @@ -779,7 +855,7 @@ int main(int argc, char **argv) if (reply->exec_result == EXEC_TYPE_NO_EXIST_MCLAGID) { - fprintf(stderr, "Mclag-id %d hasn't been configured in iccpd!\n", mclag_id); + fprintf(stderr, "Mclag-id %d hasn't been configured in iccpd!\n", para_int); ret = EXIT_FAILURE; goto mclagdctl_disconnect; } diff --git a/src/iccpd/src/mclagdctl/mclagdctl.h b/src/iccpd/src/mclagdctl/mclagdctl.h index 049e301a66d6..2c9a24d57ba1 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.h +++ b/src/iccpd/src/mclagdctl/mclagdctl.h @@ -53,6 +53,8 @@ enum id_command_type ID_CMDTYPE_D_P, ID_CMDTYPE_D_P_L, ID_CMDTYPE_D_P_P, + ID_CMDTYPE_C, + ID_CMDTYPE_C_L, }; enum mclagdctl_notify_peer_type @@ -63,9 +65,20 @@ enum mclagdctl_notify_peer_type INFO_TYPE_DUMP_MAC, INFO_TYPE_DUMP_LOCAL_PORTLIST, INFO_TYPE_DUMP_PEER_PORTLIST, + INFO_TYPE_CONFIG_LOGLEVEL, INFO_TYPE_FINISH, }; +enum log_level_type +{ + CRITICAL = 0, + ERR= 1, + WARN = 2, + NOTICE= 3, + INFO = 4, + DEBUG = 5 +}; + struct mclagdctl_req_hdr { int info_type; @@ -179,4 +192,6 @@ extern int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc extern int mclagdctl_parse_dump_local_portlist(char *msg, int data_len); extern int mclagdctl_enca_dump_peer_portlist(char *msg, int mclag_id, int argc, char **argv); extern int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len); +int mclagdctl_enca_config_loglevel(char *msg, int log_level, int argc, char **argv); +int mclagdctl_parse_config_loglevel(char *msg, int data_len); diff --git a/src/iccpd/src/mlacp_fsm.c b/src/iccpd/src/mlacp_fsm.c index d40466e6221b..f479b75f36cc 100644 --- a/src/iccpd/src/mlacp_fsm.c +++ b/src/iccpd/src/mlacp_fsm.c @@ -149,7 +149,7 @@ static void mlacp_sync_send_sysConf(struct CSM* csm) if (msg_len > 0) iccp_csm_send(csm, g_csm_buf, msg_len); else - ICCPD_LOG_WARN("mlacp_fsm", " Invalid sysconf packet."); + ICCPD_LOG_WARN(__FUNCTION__, "Invalid sysconf packet."); /*ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] SysConf, len=[%d]", msg_len);*/ @@ -353,7 +353,7 @@ static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg) if (mlacp_fsm_update_system_conf(csm, sysconf) == MCLAG_ERROR) { /*NOTE: we just change the node ID local side without sending NAK msg*/ - ICCPD_LOG_DEBUG("mlacp_fsm", " Same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id); + ICCPD_LOG_DEBUG(__FUNCTION__, "Same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id); mlacp_sync_send_nak_handler(csm, msg); } @@ -603,7 +603,7 @@ void mlacp_fsm_transit(struct CSM* csm) if ((time(NULL) - csm->warm_reboot_disconn_time) >= WARM_REBOOT_TIMEOUT) { csm->warm_reboot_disconn_time = 0; - ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot, reconnection timeout, recover to normal reboot!"); + ICCPD_LOG_NOTICE(__FUNCTION__, "Peer warm reboot, reconnection timeout, recover to normal reboot!"); mlacp_peer_disconn_handler(csm); } } @@ -808,7 +808,7 @@ static void mlacp_sync_send_nak_handler(struct CSM* csm, struct Msg* msg) icc_hdr = (ICCHdr*)msg->buf; - ICCPD_LOG_WARN("mlacp_fsm", " ### Send NAK ###"); + ICCPD_LOG_WARN(__FUNCTION__, "Send NAK"); memset(g_csm_buf, 0, CSM_BUFFER_SIZE); csm->app_csm.invalid_msg_id = ntohl(icc_hdr->ldp_hdr.msg_id); @@ -822,7 +822,7 @@ static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg) uint16_t tlvType = -1; int i; - ICCPD_LOG_WARN("mlacp_fsm", " ### Receive NAK ###"); + ICCPD_LOG_WARN(__FUNCTION__, "Receive NAK "); /* Dequeuq NAK*/ naktlv = (NAKTLV*)&msg->buf[sizeof(ICCHdr)]; @@ -844,18 +844,18 @@ static void mlacp_sync_recv_nak_handler(struct CSM* csm, struct Msg* msg) case TLV_T_MLACP_SYSTEM_CONFIG: MLACP(csm).node_id--; MLACP(csm).system_config_changed = 1; - ICCPD_LOG_WARN("mlacp_fsm", " [%X] change NodeID as %d", tlvType & 0x00FF, MLACP(csm).node_id); + ICCPD_LOG_WARN(__FUNCTION__, "[%X] change NodeID as %d", tlvType & 0x00FF, MLACP(csm).node_id); break; default: - ICCPD_LOG_WARN("mlacp_fsm", " [%X]", tlvType & 0x00FF); + ICCPD_LOG_WARN(__FUNCTION__, " [%X]", tlvType & 0x00FF); MLACP(csm).need_to_sync = 1; break; } } else { - ICCPD_LOG_WARN("mlacp_fsm", " Unknow NAK"); + ICCPD_LOG_WARN(__FUNCTION__, "Unknow NAK"); MLACP(csm).need_to_sync = 1; } @@ -1201,7 +1201,7 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg) if ((time(NULL) - csm->peer_warm_reboot_time) >= WARM_REBOOT_TIMEOUT) { csm->peer_warm_reboot_time = 0; - ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot timeout, recover to normal reboot!"); + ICCPD_LOG_NOTICE(__FUNCTION__, "Peer warm reboot timeout, recover to normal reboot!"); } } diff --git a/src/iccpd/src/mlacp_link_handler.c b/src/iccpd/src/mlacp_link_handler.c index b2a917d5ae9b..66a75c4b8620 100644 --- a/src/iccpd/src/mlacp_link_handler.c +++ b/src/iccpd/src/mlacp_link_handler.c @@ -234,8 +234,8 @@ static int arp_set_handler(struct CSM* csm, arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]); mlacp_fsm_arp_set(arp_msg->ifname, arp_msg->ipv4_addr, mac_str); - ICCPD_LOG_DEBUG(__FUNCTION__, "Add dynamic ARP to kernel [%s]", - show_ip_str(htonl(arp_msg->ipv4_addr))); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Add dynamic ARP to kernel [%s]", + show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } goto done; @@ -253,10 +253,10 @@ static int arp_set_handler(struct CSM* csm, if (arp_msg->op_type == ARP_SYNC_DEL) continue; + /* link broken, del all dynamic arp on the lif*/ mlacp_fsm_arp_del(arp_msg->ifname, arp_msg->ipv4_addr); - /* link broken, del all static arp on the lif*/ - ICCPD_LOG_DEBUG(__FUNCTION__, "Del dynamic ARP [%s]", - show_ip_str(htonl(arp_msg->ipv4_addr))); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "Del dynamic ARP [%s]", + show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } done: @@ -302,7 +302,7 @@ static void set_route_by_linux_route(struct CSM* csm, #endif ret = system(syscmd); - ICCPD_LOG_DEBUG(__FUNCTION__, " %s ret = %d", syscmd, ret); + ICCPD_LOG_DEBUG(__FUNCTION__, "%s ret = %d", syscmd, ret); return; } @@ -363,8 +363,8 @@ static void set_l3_itf_state(struct CSM *csm, { /*set_default_route(csm);*/ - ICCPD_LOG_DEBUG(__FUNCTION__, " route set Interface = %s route type = %d route = %s nexthop via = %s ", - set_l3_local_if->name, route_type, show_ip_str(htonl(set_l3_local_if->ipv4_addr)), csm->peer_ip ); + /*ICCPD_LOG_DEBUG(__FUNCTION__, " route set Interface = %s route type = %d route = %s nexthop via = %s ", + set_l3_local_if->name, route_type, show_ip_str(htonl(set_l3_local_if->ipv4_addr)), csm->peer_ip );*/ /* set static route*/ if (route_type == ROUTE_ADD) @@ -428,7 +428,7 @@ static void mlacp_clean_fdb(void) if (sys->sync_fd) write(sys->sync_fd, msg_buf, msg_hdr->len); - ICCPD_LOG_DEBUG(__FUNCTION__, "notify mclagsyncd clear fdb"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Notify mclagsyncd to clear FDB"); return; } @@ -467,8 +467,8 @@ void set_peerlink_mlag_port_learn(struct LocalInterface *lif, int enable) msg_hdr->len += sizeof(mclag_sub_option_hdr_t); msg_hdr->len += sub_msg->op_len; - ICCPD_LOG_DEBUG(__FUNCTION__, " send port-learn msg to sync for %s , member %s", - lif->name, sub_msg->data); + ICCPD_LOG_DEBUG(__FUNCTION__, "Send %s port MAC learn msg to mclagsyncd for %s", + sub_msg->op_type == MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE ? "DISABLE":"ENABLE", lif->name); /*send msg*/ if (sys->sync_fd) @@ -600,7 +600,11 @@ void update_peerlink_isolate_from_all_csm_lif( if (dst_len) { memcpy(sub_msg->data, mlag_po_buf, dst_len); - ICCPD_LOG_DEBUG(__FUNCTION__, "isolate dst %s, data %s, len %d", mlag_po_buf, sub_msg->data, dst_len); + ICCPD_LOG_DEBUG(__FUNCTION__, "Send port isolate msg to mclagsyncd, src port %s, dst port %s", csm->peer_link_if->name, mlag_po_buf); + } + else + { + ICCPD_LOG_DEBUG(__FUNCTION__, "Send port isolate msg to mclagsyncd, src port %s, dst port is NULL", csm->peer_link_if->name); } /*send msg*/ @@ -683,11 +687,11 @@ void update_peerlink_isolate_from_pif( if (!lif) { - ICCPD_LOG_DEBUG(__FUNCTION__, "can't find lif"); + ICCPD_LOG_WARN(__FUNCTION__, "Can't find local if for %s", pif->name); return; } - ICCPD_LOG_DEBUG(__FUNCTION__, " from peer %s local(%s) / peer(%s)", + ICCPD_LOG_DEBUG(__FUNCTION__, "From if %s local(%s) / peer(%s)", lif->name, (lif_po_state) ? "up" : "down", (pif_po_state) ? "up" : "down"); @@ -697,7 +701,7 @@ void update_peerlink_isolate_from_pif( if (pif_po_state == 1) { /* both peer-pair link up, enable port-isolate*/ - ICCPD_LOG_DEBUG(__FUNCTION__, " Enable port-isolate from %s to %s", + ICCPD_LOG_DEBUG(__FUNCTION__, "Enable port-isolate from %s to %s", csm->peer_link_if->name, lif->name); set_peerlink_mlag_port_isolate(csm, lif, 1); } @@ -741,7 +745,7 @@ static void update_peerlink_isolate_from_lif( break; } - ICCPD_LOG_DEBUG(__FUNCTION__, " from local %s local(%s) / peer(%s)", + ICCPD_LOG_DEBUG(__FUNCTION__, "From if %s local(%s) / peer(%s)", lif->name, (lif_po_state) ? "up" : "down", (pif_po_state) ? "up" : "down"); if (lif_po_state == 1) @@ -903,11 +907,11 @@ void syn_arp_info_to_peer(struct CSM *csm, struct LocalInterface *local_if) if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG( __FUNCTION__, "Enqueue ARP[ADD] for %s", - show_ip_str(htonl(arp_msg->ipv4_addr))); + /*ICCPD_LOG_DEBUG( __FUNCTION__, "Enqueue ARP[ADD] for %s", + show_ip_str(htonl(arp_msg->ipv4_addr)));*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s", show_ip_str(htonl(arp_msg->ipv4_addr))); } } @@ -995,8 +999,7 @@ void iccp_get_fdb_change_from_syncd( void) msg_hdr->type = MCLAG_MSG_TYPE_GET_FDB_CHANGES; msg_hdr->len = sizeof(struct IccpSyncdHDr); - ICCPD_LOG_DEBUG(__FUNCTION__, "fd %d write get fdb change msg ", - sys->sync_fd); + ICCPD_LOG_DEBUG(__FUNCTION__, "Send get fdb change msg to mclagsyncd"); /*send msg*/ if (sys->sync_fd > 0) @@ -1031,8 +1034,8 @@ void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg, uint8_t mac_type) mac_info->op_type = mac_msg->op_type; msg_hdr->len = sizeof(struct IccpSyncdHDr) + sizeof(struct mclag_fdb_info); - ICCPD_LOG_DEBUG(__FUNCTION__, "write mac msg vid : %d ; ifname %s ; mac %s fdb type %s ; op type %s", - mac_info->vid, mac_info->port_name, mac_info->mac, mac_info->type == MAC_TYPE_STATIC ? "static" : "dynamic", mac_info->op_type == MAC_SYNC_ADD ? "add" : "del"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Send mac %s msg to mclagsyncd, vid %d ; ifname %s ; mac %s; type %s", + mac_info->op_type == MAC_SYNC_ADD ? "add" : "del", mac_info->vid, mac_info->port_name, mac_info->mac, mac_info->type == MAC_TYPE_STATIC ? "static" : "dynamic"); /*send msg*/ if (sys->sync_fd > 0 ) @@ -1078,9 +1081,14 @@ uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);*/ } + else + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue MAC-msg-list: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + } } } else/*set age flag*/ @@ -1097,8 +1105,13 @@ uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t if (iccp_csm_init_msg(&msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0) { TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + /*ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);*/ + } + else + { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue MAC-msg-list: %s, del %s vlan-id %d, age_flag %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); } } } @@ -1128,10 +1141,10 @@ static void update_l2_mac_state(struct CSM *csm, /*portchannel down*/ if (po_state == 0) { - mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s down, age local MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down,flag %d del MAC: %s, MAC %s vlan-id %d", - mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) { @@ -1139,7 +1152,7 @@ static void update_l2_mac_state(struct CSM *csm, if (mac_msg->fdb_type != MAC_TYPE_STATIC) del_mac_from_chip(mac_msg); - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, del MAC: %s, MAC %s vlan-id %d", + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s down, del MAC %s vlan-id %d", mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); /*If local and peer both aged, del the mac*/ @@ -1167,16 +1180,16 @@ static void update_l2_mac_state(struct CSM *csm, memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); } - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, flag %d, redirect MAC to peer-link: %s, MAC %s vlan-id %d", - mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s down, redirect MAC %s vlan-id %d to peer-link %s", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, csm->peer_itf_name); } else { /*peer-link is not configured, del mac from ASIC, mac still in mac_list*/ del_mac_from_chip(mac_msg); - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf down, flag %d, peer-link is not configured: %s, MAC %s vlan-id %d", - mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s down, peer-link is not configured: MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); } } } @@ -1186,8 +1199,8 @@ static void update_l2_mac_state(struct CSM *csm, /*when this portchannel up, recover the mac back*/ if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf up, redirect MAC to portchannel: %s, MAC %s vlan-id %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s up, redirect MAC %s vlan-id %d from peerlink to %s", + mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->origin_ifname); /*Remove MAC_AGE_LOCAL flag*/ mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 0); @@ -1202,7 +1215,7 @@ static void update_l2_mac_state(struct CSM *csm, { /*this may be peerlink is not configured and portchannel is down*/ /*when this portchannel up, add the mac back to ASIC*/ - ICCPD_LOG_DEBUG(__FUNCTION__, "Intf up, add MAC to ASIC: %s, MAC %s vlan-id %d", + ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s up, add MAC %s vlan-id %d to ASIC", mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); /*Remove MAC_AGE_LOCAL flag*/ @@ -1268,8 +1281,8 @@ static void mlacp_conn_handler_fdb(struct CSM* csm) { mac_msg->age_flag &= ~MAC_AGE_PEER; TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail); - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); } } else @@ -1277,8 +1290,8 @@ static void mlacp_conn_handler_fdb(struct CSM* csm) /*If MAC with local age flag and is point to MCLAG enabled port, reomove local age flag*/ if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list not enqueue for local age flag: %s, mac %s vlan-id %d, age_flag %d, remove local age flag", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list not enqueue for local age flag: %s, mac %s vlan-id %d, remove local age flag", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); mac_msg->age_flag &= ~MAC_AGE_LOCAL; } } @@ -1428,8 +1441,8 @@ void mlacp_peer_disconn_handler(struct CSM* csm) mac_msg = (struct MACMsg*)msg->buf; mac_msg->age_flag |= MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, add %s vlan-id %d, op_type %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); /* find the MAC that the port is peer-link or local and peer both aged, to be deleted*/ if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0 && mac_msg->age_flag != (MAC_AGE_LOCAL | MAC_AGE_PEER)) @@ -1507,11 +1520,11 @@ void mlacp_peerlink_down_handler(struct CSM* csm) if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0) continue; - mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); - ICCPD_LOG_DEBUG(__FUNCTION__, "Peer link down, del MAC for peer-link: %s, MAC %s vlan-id %d", mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); + mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1); + /*Send mac del message to mclagsyncd*/ del_mac_from_chip(mac_msg); @@ -1604,7 +1617,7 @@ int iccp_connect_syncd() goto conn_fail; } - ICCPD_LOG_WARN(__FUNCTION__, "success to link syncd"); + ICCPD_LOG_NOTICE(__FUNCTION__, "Success to link syncd"); sys->sync_fd = fd; event.data.fd = fd; @@ -1616,8 +1629,7 @@ int iccp_connect_syncd() conn_fail: if (count == 0) - ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclag syncd socket connect fail", - __FUNCTION__, __LINE__); + ICCPD_LOG_DEBUG(__FUNCTION__, "Mclag syncd socket connect fail"); count++; @@ -1674,7 +1686,7 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch mac_msg->age_flag = 0; - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC msg vid %d mac %s port %s optype %s ", vid, mac_str, ifname, op_type == MAC_SYNC_ADD ? "add" : "del"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC msg from mclagsyncd, vid %d mac %s port %s optype %s ", vid, mac_str, ifname, op_type == MAC_SYNC_ADD ? "add" : "del"); /*Debug*/ #if 0 /* dump receive MAC info*/ @@ -1812,8 +1824,8 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch } else { - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC-msg-list: %s, add %s vlan-id %d, age_flag %d", - mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag); + ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue MAC-msg-list: %s, MAC %s vlan-id %d", + mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); } } @@ -1826,7 +1838,7 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);*/ } else - ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC %s, add %s vlan-id %d", + ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue MAC %s, MAC %s vlan-id %d", mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); } } @@ -1981,6 +1993,8 @@ char * mclagd_ctl_cmd_str(int req_type) case INFO_TYPE_DUMP_PEER_PORTLIST: return "dump peer portlist"; + case INFO_TYPE_CONFIG_LOGLEVEL: + return "config loglevel"; default: break; } @@ -2005,7 +2019,7 @@ int mclagd_ctl_sock_create() sys->sync_ctrl_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (sys->sync_ctrl_fd < 0) { - ICCPD_LOG_WARN(__FUNCTION__, "Failed to create mclagd ctl sock\n"); + ICCPD_LOG_WARN(__FUNCTION__, "Failed to create mclagd ctl sock"); return sys->sync_ctrl_fd; } @@ -2018,14 +2032,14 @@ int mclagd_ctl_sock_create() if ((ret = bind(sys->sync_ctrl_fd, (struct sockaddr*)&addr, addr_len)) < 0) { - ICCPD_LOG_WARN(__FUNCTION__, "Failed to bind mclagd ctl socket %s:%s\n", sys->mclagdctl_file_path, strerror(errno)); + ICCPD_LOG_WARN(__FUNCTION__, "Failed to bind mclagd ctl socket %s:%s", sys->mclagdctl_file_path, strerror(errno)); close(sys->sync_ctrl_fd); return MCLAG_ERROR; } if (listen(sys->sync_ctrl_fd, 5) < 0) { - ICCPD_LOG_WARN(__FUNCTION__, "Failed to listen unix mclagd ctl socket%s:%s\n", sys->mclagdctl_file_path, strerror(errno)); + ICCPD_LOG_WARN(__FUNCTION__, "Failed to listen unix mclagd ctl socket%s:%s", sys->mclagdctl_file_path, strerror(errno)); close(sys->sync_ctrl_fd); return MCLAG_ERROR; } @@ -2048,7 +2062,7 @@ int mclagd_ctl_sock_accept(int fd) client_fd = accept(fd, (struct sockaddr*)&client_addr, &addr_len); if (client_fd < 0) { - ICCPD_LOG_WARN(__FUNCTION__, "failed to accept a client from mclagdctl\n"); + ICCPD_LOG_WARN(__FUNCTION__, "Failed to accept a client from mclagdctl"); return MCLAG_ERROR; } @@ -2121,7 +2135,6 @@ void mclagd_ctl_handle_dump_state(int client_fd, int mclag_id) int len_tmp = 0; ret = iccp_mclag_config_dump(&Pbuf, &state_num, mclag_id); - ICCPD_LOG_WARN(__FUNCTION__, "state_num = %d", state_num); if (ret != EXEC_TYPE_SUCCESS) { len_tmp = sizeof(struct mclagd_reply_hdr); @@ -2314,6 +2327,25 @@ void mclagd_ctl_handle_dump_peer_portlist(int client_fd, int mclag_id) return; } +void mclagd_ctl_handle_config_loglevel(int client_fd, int log_level) +{ + char buf[sizeof(struct mclagd_reply_hdr)+sizeof(int)]; + struct mclagd_reply_hdr *hd = NULL; + int len_tmp = 0; + + logger_set_configuration(log_level); + + len_tmp = sizeof(struct mclagd_reply_hdr); + memcpy(buf, &len_tmp, sizeof(int)); + hd = (struct mclagd_reply_hdr *)(buf + sizeof(int)); + hd->exec_result = EXEC_TYPE_SUCCESS; + hd->info_type = INFO_TYPE_CONFIG_LOGLEVEL; + hd->data_len = 0; + mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR); + + return; +} + int mclagd_ctl_interactive_process(int client_fd) { char buf[512] = { 0 }; @@ -2331,7 +2363,7 @@ int mclagd_ctl_interactive_process(int client_fd) req = (struct mclagdctl_req_hdr*)buf; - ICCPD_LOG_WARN(__FUNCTION__, "rcv request %s from mclagdctl", mclagd_ctl_cmd_str(req->info_type)); + ICCPD_LOG_DEBUG(__FUNCTION__, "Receive request %s from mclagdctl", mclagd_ctl_cmd_str(req->info_type)); switch (req->info_type) { @@ -2355,6 +2387,10 @@ int mclagd_ctl_interactive_process(int client_fd) mclagd_ctl_handle_dump_peer_portlist(client_fd, req->mclag_id); break; + case INFO_TYPE_CONFIG_LOGLEVEL: + mclagd_ctl_handle_config_loglevel(client_fd, req->mclag_id); + break; + default: return MCLAG_ERROR; } diff --git a/src/iccpd/src/mlacp_sync_prepare.c b/src/iccpd/src/mlacp_sync_prepare.c index fb9ed0aac5fa..f40a59884e49 100644 --- a/src/iccpd/src/mlacp_sync_prepare.c +++ b/src/iccpd/src/mlacp_sync_prepare.c @@ -326,9 +326,8 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu sprintf(MacData->ifname, "%s", mac_msg->origin_ifname); MacData->vid = htons(mac_msg->vid); - #if 1 - ICCPD_LOG_DEBUG(__FUNCTION__, "Send MAC messge to peer, port %s mac = %s, vid = %d, type = %s count %d ", mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count); - #endif + ICCPD_LOG_DEBUG(__FUNCTION__, "Send MAC messge to peer, port %s mac = %s, vid = %d, type = %s count %d ", mac_msg->origin_ifname, + mac_msg->mac_str, mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count); return msg_len; } @@ -455,11 +454,11 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, tlv->vlanData[num_of_vlan_id].vlan_id = htons(vlan_id->vid); num_of_vlan_id++; - ICCPD_LOG_DEBUG(__FUNCTION__, " port channel %d: addr = %s vlan id %d num %d ", port_channel->po_id, show_ip_str( tlv->ipv4_addr), vlan_id->vid, num_of_vlan_id ); + ICCPD_LOG_DEBUG(__FUNCTION__, "PortChannel%d: ipv4 addr = %s vlan id %d num %d ", port_channel->po_id, show_ip_str( tlv->ipv4_addr), vlan_id->vid, num_of_vlan_id ); } } - ICCPD_LOG_DEBUG(__FUNCTION__, " port channel %d: addr = %s l3 mode %d", port_channel->po_id, show_ip_str( tlv->ipv4_addr), tlv->l3_mode); + ICCPD_LOG_DEBUG(__FUNCTION__, "PortChannel%d: ipv4 addr = %s l3 mode %d", port_channel->po_id, show_ip_str( tlv->ipv4_addr), tlv->l3_mode); return msg_len; } @@ -510,8 +509,7 @@ int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, memcpy(tlv->if_name, peerlink_port->name, MAX_L_PORT_NAME); tlv->port_type = peerlink_port->type; - - ICCPD_LOG_DEBUG(__FUNCTION__, " peerlink port info portname %s type = %d", tlv->if_name, tlv->port_type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Peerlink port is %s, type = %d", tlv->if_name, tlv->port_type); return msg_len; } diff --git a/src/iccpd/src/mlacp_sync_update.c b/src/iccpd/src/mlacp_sync_update.c index e98ed9015c5d..40dc33187885 100644 --- a/src/iccpd/src/mlacp_sync_update.c +++ b/src/iccpd/src/mlacp_sync_update.c @@ -51,7 +51,7 @@ int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV*sysconf) MLACP(csm).remote_system.system_priority = ntohs(sysconf->sys_priority); MLACP(csm).remote_system.node_id = sysconf->node_id; - ICCPD_LOG_DEBUG(__FUNCTION__, " SystemID [%02X:%02X:%02X:%02X:%02X:%02X]. SystemPriority [%d], Remote NodeID [%d], NodeID [%d]", + ICCPD_LOG_DEBUG(__FUNCTION__, "SystemID [%02X:%02X:%02X:%02X:%02X:%02X], SystemPriority [%d], Remote NodeID [%d], NodeID [%d]", MLACP(csm).remote_system.system_id[0], MLACP(csm).remote_system.system_id[1], MLACP(csm).remote_system.system_id[2], MLACP(csm).remote_system.system_id[3], MLACP(csm).remote_system.system_id[4], MLACP(csm).remote_system.system_id[5], MLACP(csm).remote_system.system_priority, @@ -76,7 +76,7 @@ int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf) uint8_t po_active; uint8_t new_create = 0; - ICCPD_LOG_DEBUG(__FUNCTION__, " Port name %s, po id %d flag %d MAC[%02x:%02x:%02x:%02x:%02x:%02x] ", + ICCPD_LOG_DEBUG(__FUNCTION__, "Port name %s, po id %d flag %d MAC[%02x:%02x:%02x:%02x:%02x:%02x] ", portconf->agg_name, ntohs(portconf->agg_id), portconf->flags, portconf->mac_addr[0], portconf->mac_addr[1], portconf->mac_addr[2], portconf->mac_addr[3], portconf->mac_addr[4], portconf->mac_addr[5] ); @@ -129,7 +129,7 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) if (csm == NULL || tlv == NULL) return MCLAG_ERROR; - ICCPD_LOG_DEBUG(__FUNCTION__, " po id %d state %d ", ntohs(tlv->agg_id), tlv->agg_state); + ICCPD_LOG_DEBUG(__FUNCTION__, "Portchannel id %d state %d", ntohs(tlv->agg_id), tlv->agg_state); po_active = (tlv->agg_state == PORT_STATE_UP); @@ -147,7 +147,7 @@ int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv) update_peerlink_isolate_from_pif(csm, peer_if, po_active, 0); peer_if->po_active = po_active; - ICCPD_LOG_DEBUG(__FUNCTION__, "Update Msg for %s state %s", peer_if->name, tlv->agg_state ? "down" : "up"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update peer interface %s to state %s", peer_if->name, tlv->agg_state ? "down" : "up"); break; } @@ -166,11 +166,9 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * struct LocalInterface* local_if = NULL; uint8_t from_mclag_intf = 0;/*0: orphan port, 1: MCLAG port*/ -#if 1 ICCPD_LOG_INFO(__FUNCTION__, "Received MAC Info, port[%s] vid[%d] MAC[%s] type[%s]", MacData->ifname, ntohs(MacData->vid), MacData->mac_str, MacData->type == MAC_SYNC_ADD ? "add" : "del"); -#endif /*Find the interface in MCLAG interface list*/ LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next) @@ -193,12 +191,12 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * if (MacData->type == MAC_SYNC_ADD) { mac_msg->age_flag &= ~MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, add %s vlan-id %d", + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, Remove peer age flag:%d ifname %s, MAC %s vlan-id %d", mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); /*mac_msg->fdb_type = tlv->fdb_type;*/ /*The port ifname is different to the local item*/ - if (strcmp(mac_msg->ifname, MacData->ifname) != 0 || strcmp(mac_msg->origin_ifname, MacData->ifname) != 0) + if (from_mclag_intf == 0 || strcmp(mac_msg->ifname, MacData->ifname) != 0 || strcmp(mac_msg->origin_ifname, MacData->ifname) != 0) { if (mac_msg->fdb_type != MAC_TYPE_STATIC) { @@ -216,8 +214,8 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * { if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0) { - /*This MAC is already point to peer-link*/ - return; + /* This MAC is already point to peer-link */ + return 0; } if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP) @@ -298,7 +296,7 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * if (msg && MacData->type == MAC_SYNC_DEL) { mac_msg->age_flag |= MAC_AGE_PEER; - ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer age flag: %d ifname %s, add %s vlan-id %d", + ICCPD_LOG_DEBUG(__FUNCTION__, "Recv DEL, Add peer age flag: %d ifname %s, MAC %s vlan-id %d", mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER)) @@ -334,7 +332,7 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * if (strlen(csm->peer_itf_name) == 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "From orphan port or portchannel is down, but peer-link is not configured: ifname %s, add %s vlan-id %d", + ICCPD_LOG_DEBUG(__FUNCTION__, "From orphan port or portchannel is down, but peer-link is not configured: ifname %s, MAC %s vlan-id %d", mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); /*if orphan port mac but no peerlink, don't keep this mac*/ @@ -346,7 +344,7 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData * /*Redirect the mac to peer-link*/ memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ); - ICCPD_LOG_DEBUG(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, add %s vlan-id %d", + ICCPD_LOG_DEBUG(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, MAC %s vlan-id %d", mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid); } } @@ -398,7 +396,7 @@ int mlacp_fsm_update_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* if (!csm || !tlv) return MCLAG_ERROR; count = ntohs(tlv->num_of_entry); - ICCPD_LOG_INFO(__FUNCTION__, "Received MAC Info count %d ", count ); + ICCPD_LOG_INFO(__FUNCTION__, "Received MAC Info count %d", count ); for (i = 0; i < count; i++) { @@ -448,16 +446,14 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) if (!csm || !arp_entry) return MCLAG_ERROR; - #if 1 + sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2], + arp_entry->mac_addr[3], arp_entry->mac_addr[4], arp_entry->mac_addr[5]); + ICCPD_LOG_INFO(__FUNCTION__, "Received ARP Info, intf[%s] IP[%s], MAC[%02x:%02x:%02x:%02x:%02x:%02x]", arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2], arp_entry->mac_addr[3], arp_entry->mac_addr[4], arp_entry->mac_addr[5]); - #endif - - sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2], - arp_entry->mac_addr[3], arp_entry->mac_addr[4], arp_entry->mac_addr[5]); if (strncmp(arp_entry->ifname, "Vlan", 4) == 0) { @@ -475,8 +471,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, - "ARP is learnt from intf %s, peer-link %s is the member of this vlan", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is learnt from intf %s, peer-link %s is the member of this vlan", vlan_id_list->vlan_itf->name, peer_link_if->name); /* Peer-link belong to L3 vlan is alive, set the ARP info*/ @@ -505,8 +500,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) if (!local_if_is_l3_mode(vlan_id_list->vlan_itf)) continue; - ICCPD_LOG_DEBUG(__FUNCTION__, - "ARP is learnt from intf %s, mclag %s is the member of this vlan", + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is learnt from intf %s, mclag %s is the member of this vlan", vlan_id_list->vlan_itf->name, local_if->name); break; } @@ -523,9 +517,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) /* Is the ARP belong to a L3 mode MLAG itf?*/ if (strcmp(local_if->name, arp_entry->ifname) == 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, - "ARP is learnt from mclag L3 intf %s", - local_if->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "ARP is learnt from mclag L3 intf %s", local_if->name); if (local_if->po_active == 1) { /* po is alive, set the ARP info*/ @@ -549,7 +541,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) { if (mlacp_fsm_arp_set(arp_entry->ifname, ntohl(arp_entry->ipv4_addr), mac_str) < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP add failure for %s %s %s", + ICCPD_LOG_WARN(__FUNCTION__, "ARP add failure for %s %s %s", arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); return MCLAG_ERROR; } @@ -558,7 +550,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry) { if (mlacp_fsm_arp_del(arp_entry->ifname, ntohl(arp_entry->ipv4_addr)) < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "ARP delete failure for %s %s %s", + ICCPD_LOG_WARN(__FUNCTION__, "ARP delete failure for %s %s %s", arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str); return MCLAG_ERROR; } @@ -688,7 +680,7 @@ int mlacp_fsm_update_port_channel_info(struct CSM* csm, iccp_consistency_check(peer_if->name); - ICCPD_LOG_DEBUG(__FUNCTION__, "port channel %s info ip %s l3 mode %d", peer_if->name, show_ip_str( tlv->ipv4_addr), peer_if->l3_mode); + ICCPD_LOG_DEBUG(__FUNCTION__, "Peer intf %s info: ipv4 addr %s l3 mode %d", peer_if->name, show_ip_str( tlv->ipv4_addr), peer_if->l3_mode); break; } @@ -706,15 +698,15 @@ int mlacp_fsm_update_peerlink_info(struct CSM* csm, if (!csm->peer_link_if) { - ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port info from peer, local peerlink is not exist!"); + ICCPD_LOG_WARN(__FUNCTION__, "Peerlink port info recv from peer, local peerlink is not exist!"); return 0; } if (csm->peer_link_if->type != tlv->port_type) - ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port type of peer %d is not same with local %d !", tlv->port_type, csm->peer_link_if->type); + ICCPD_LOG_DEBUG(__FUNCTION__, "Peerlink port type of peer %d is not same with local %d !", tlv->port_type, csm->peer_link_if->type); if (tlv->port_type == IF_T_VXLAN && strncmp(csm->peer_itf_name, tlv->if_name, strlen(csm->peer_itf_name))) - ICCPD_LOG_DEBUG(__FUNCTION__, "peerlink port is vxlan port and peerlink port at peer %s is not same with local peerlink port %s !", tlv->if_name, csm->peer_itf_name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Peerlink port is vxlan port, but peerlink port of peer %s is not same with local %s !", tlv->if_name, csm->peer_itf_name); return 0; } diff --git a/src/iccpd/src/port.c b/src/iccpd/src/port.c index 3e985981188d..1414a1f86c87 100644 --- a/src/iccpd/src/port.c +++ b/src/iccpd/src/port.c @@ -29,75 +29,6 @@ #include "../include/system.h" #include "../include/iccp_csm.h" -/* Ethernet MAC Address setter - set by string. */ -static void ether_mac_set_addr_with_string(uint8_t* macdst, const char* macstr) -{ - char* dupmac = NULL; - char* token = NULL; - unsigned long oct; - int i = 0; - - if (macdst == NULL || macstr == NULL) - return; - - memset(macdst, 0, 6); - - dupmac = strdup(macstr); - - /* tokenize */ - token = strtok(dupmac, " -:"); - oct = strtoul(token, NULL, 16); - if (oct > 255) - oct = 0xff; - macdst[0] = oct; - - for (i = 1; i < 6; ++i) - { - token = strtok(NULL, " -:"); - if (token == NULL) - { - memset(macdst, 0, 6); - break; - } - oct = strtoul(token, NULL, 16); - if (oct > 255) - oct = 0xff; - macdst[i] = oct; - } - - free(dupmac); - - return; -} - -/* Get the Ethernet MAC Address by interface name. */ -void ether_mac_set_addr_with_if_name(char* name, uint8_t* mac) -{ - char addr_file[64]; - FILE *file_ptr = NULL; - char buf[64]; - - if (!mac || !name) - return; - - memset(addr_file, 0, 64); - snprintf(addr_file, 63, "/sys/class/net/%s/address", name); - - if ((file_ptr = fopen(addr_file, "r"))) - { - memset(buf, 0, 64); - fgets(buf, 63, file_ptr); - fclose(file_ptr); - ether_mac_set_addr_with_string(mac, buf); - } - else - { - ICCPD_LOG_WARN(__FUNCTION__, "Failed to find device %s from %s", name, addr_file); - } - - return; -} - void local_if_init(struct LocalInterface* local_if) { if (local_if == NULL) @@ -152,7 +83,7 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type) if (!(local_if = (struct LocalInterface*)malloc(sizeof(struct LocalInterface)))) { - ICCPD_LOG_WARN(__FUNCTION__, "port ifindex = %d, malloc failed", ifindex); + ICCPD_LOG_WARN(__FUNCTION__, "Port ifindex = %d, malloc failed", ifindex); return NULL; } @@ -196,13 +127,13 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type) break; default: - ICCPD_LOG_WARN(__FUNCTION__, "the type of local interface (%s) is not acceptable", ifname); + ICCPD_LOG_WARN(__FUNCTION__, "The type of local interface (%s) is not acceptable", ifname); if (local_if) free(local_if); return NULL; } - ICCPD_LOG_INFO(__FUNCTION__, + ICCPD_LOG_NOTICE(__FUNCTION__, "Create a local_if = %s ifindex = %d MAC = %02x:%02x:%02x:%02x:%02x:%02x, state = %s", ifname, local_if->ifindex, local_if->mac_addr[0], local_if->mac_addr[1], local_if->mac_addr[2], local_if->mac_addr[3], local_if->mac_addr[4], local_if->mac_addr[5], local_if->state ? "down" : "up"); @@ -355,7 +286,7 @@ void local_if_destroy(char *ifname) if (!lif) return; - ICCPD_LOG_WARN(__FUNCTION__, "destroy interface %s, %d\n", lif->name, lif->ifindex); + ICCPD_LOG_WARN(__FUNCTION__, "Destroy interface %s, %d\n", lif->name, lif->ifindex); if (lif->type == IF_T_VLAN) local_if_vlan_remove(lif); @@ -439,7 +370,7 @@ void local_if_purge_clear(void) while (!LIST_EMPTY(&(sys->lif_purge_list))) { lif = LIST_FIRST(&(sys->lif_purge_list)); - ICCPD_LOG_DEBUG(__FUNCTION__, "purge %s", lif->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Purge %s", lif->name); LIST_REMOVE(lif, system_purge_next); if (lif->mlacp_purge_next.le_next != 0 && lif->mlacp_purge_next.le_prev != 0) LIST_REMOVE(lif, mlacp_purge_next); @@ -484,7 +415,7 @@ struct PeerInterface* peer_if_create(struct CSM* csm, if (type != IF_T_PORT && type != IF_T_PORT_CHANNEL) { ICCPD_LOG_WARN(__FUNCTION__, - "the type(%) of peer interface(%d) is not acceptable", + "The type(%) of peer interface(%d) is not acceptable", type, peer_if_number); return NULL; } @@ -492,7 +423,7 @@ struct PeerInterface* peer_if_create(struct CSM* csm, /* create a new peer if*/ if ((peer_if = (struct PeerInterface*)malloc(sizeof(struct PeerInterface))) == NULL) { - ICCPD_LOG_WARN(__FUNCTION__, "peer port id = %d, malloc failed", peer_if_number); + ICCPD_LOG_WARN(__FUNCTION__, "Peer port id = %d, malloc failed", peer_if_number); return NULL; } memset(peer_if, 0, sizeof(struct PeerInterface)); @@ -541,8 +472,8 @@ void peer_if_del_all_vlan(struct PeerInterface* pif) while (!LIST_EMPTY(&(pif->vlan_list))) { pvlan = LIST_FIRST(&(pif->vlan_list)); - ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", - pvlan->vid, pif->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", + pif->name, pvlan->vid); LIST_REMOVE(pvlan, port_next); free(pvlan); } @@ -552,7 +483,7 @@ void peer_if_del_all_vlan(struct PeerInterface* pif) void peer_if_destroy(struct PeerInterface* pif) { - ICCPD_LOG_WARN(__FUNCTION__, "destroy peer's interface %s, %d\n", + ICCPD_LOG_WARN(__FUNCTION__, "Destroy peer's interface %s, %d", pif->name, pif->ifindex); /* destroy if*/ @@ -583,7 +514,7 @@ int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) if (!vlan) return MCLAG_ERROR; - ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d on %s", vid, local_if->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Add %s to VLAN %d", local_if->name, vid); local_if->port_config_sync = 1; LIST_INSERT_HEAD(&(local_if->vlan_list), vlan, port_next); } @@ -616,7 +547,7 @@ void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid) local_if->port_config_sync = 1; } - ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d on %s", vid, local_if->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", local_if->name, vid); return; } @@ -628,7 +559,7 @@ void local_if_del_all_vlan(struct LocalInterface* lif) while (!LIST_EMPTY(&(lif->vlan_list))) { vlan = LIST_FIRST(&(lif->vlan_list)); - ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d on %s", vlan->vid, lif->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", lif->name, vlan->vid); LIST_REMOVE(vlan, port_next); free(vlan); } @@ -649,7 +580,7 @@ int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) { if (peer_vlan->vid == vlan_id) { - ICCPD_LOG_DEBUG(__FUNCTION__, "update VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Update VLAN ID %d for peer intf %s", peer_vlan->vid, peer_if->name); break; } } @@ -660,7 +591,7 @@ int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id) if (!peer_vlan) return MCLAG_ERROR; - ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d from peer's %s", vlan_id, peer_if->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer intf %s to VLAN %d", peer_if->name, vlan_id); LIST_INSERT_HEAD(&(peer_if->vlan_list), peer_vlan, port_next); } @@ -682,7 +613,7 @@ int peer_if_clean_unused_vlan(struct PeerInterface* peer_if) { if (peer_vlan != NULL) { - ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid); LIST_REMOVE(peer_vlan, port_next); free(peer_vlan); peer_vlan = NULL; @@ -694,7 +625,7 @@ int peer_if_clean_unused_vlan(struct PeerInterface* peer_if) if (peer_vlan != NULL) { - ICCPD_LOG_DEBUG(__FUNCTION__, "remove VLAN ID = %d from peer's %s", peer_vlan->vid, peer_if->name); + ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid); LIST_REMOVE(peer_vlan, port_next); free(peer_vlan); } @@ -714,7 +645,7 @@ int set_sys_arp_accept_flag(char* ifname, int flag) snprintf(arp_file, 63, "/proc/sys/net/ipv4/conf/%s/arp_accept", ifname); if (!(file_ptr = fopen(arp_file, "r"))) { - ICCPD_LOG_DEBUG(__func__, "Failed to find device %s from %s", ifname, arp_file); + ICCPD_LOG_WARN(__func__, "Failed to find device %s from %s", ifname, arp_file); return result; } @@ -726,7 +657,7 @@ int set_sys_arp_accept_flag(char* ifname, int flag) memset(cmd, 0, 64); snprintf(cmd, 63, "echo %d > /proc/sys/net/ipv4/conf/%s/arp_accept", flag, ifname); if (system(cmd)) - ICCPD_LOG_DEBUG(__func__, "Failed to execute cmd = %s", flag, cmd); + ICCPD_LOG_WARN(__func__, "Failed to execute cmd = %s", flag, cmd); } fclose(file_ptr); diff --git a/src/iccpd/src/scheduler.c b/src/iccpd/src/scheduler.c index 7a62159a8a99..9d08e137dce0 100644 --- a/src/iccpd/src/scheduler.c +++ b/src/iccpd/src/scheduler.c @@ -74,7 +74,7 @@ static void heartbeat_check(struct CSM *csm) if ( (time(NULL) - csm->heartbeat_update_time) > HEARTBEAT_TIMEOUT_SEC) { /* hearbeat timeout*/ - ICCPD_LOG_INFO(__FUNCTION__, "iccpd connection timeout (heartbeat)"); + ICCPD_LOG_WARN(__FUNCTION__, "iccpd connection timeout (heartbeat)"); scheduler_session_disconnect_handler(csm); } @@ -149,7 +149,7 @@ int scheduler_csm_read_callback(struct CSM* csm) } else if (len == 0) { - ICCPD_LOG_INFO(__FUNCTION__, "Peer disconnect"); + ICCPD_LOG_WARN(__FUNCTION__, "Peer disconnect for receive error"); goto recv_err; } recv_len += len; @@ -169,7 +169,7 @@ int scheduler_csm_read_callback(struct CSM* csm) } else if (recv_len == 0) { - ICCPD_LOG_INFO(__FUNCTION__, "Peer disconnect"); + ICCPD_LOG_WARN(__FUNCTION__, "Peer disconnect for read error"); goto recv_err; } data_len -= recv_len; @@ -283,7 +283,7 @@ void iccp_get_start_type(struct System* sys) fp = fopen("/proc/cmdline", "r"); if (!fp) { - ICCPD_LOG_DEBUG(__FUNCTION__, "Error: Can't open file /proc/cmdline!"); + ICCPD_LOG_WARN(__FUNCTION__, "Error: Can't open file /proc/cmdline!"); return; } @@ -316,19 +316,16 @@ void scheduler_init() if (iccp_connect_syncd() < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, syncd info socket connect fail", - __FUNCTION__, __LINE__); + ICCPD_LOG_WARN(__FUNCTION__, "Syncd info socket connect fail"); } else { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, syncd info socket connect success", - __FUNCTION__, __LINE__); + ICCPD_LOG_DEBUG(__FUNCTION__, "Syncd info socket connect success"); } if (mclagd_ctl_sock_create() < 0) { - ICCPD_LOG_DEBUG(__FUNCTION__, "%s:%d, mclagd ctl info socket connect fail", - __FUNCTION__, __LINE__); + ICCPD_LOG_WARN(__FUNCTION__, "Mclagd ctl info socket connect fail"); } return; @@ -406,7 +403,7 @@ void scheduler_loop() if (sys->warmboot_exit == WARM_REBOOT) { - ICCPD_LOG_DEBUG(__FUNCTION__, "EXIT ......"); + ICCPD_LOG_DEBUG(__FUNCTION__, "Warm reboot exit ......"); return; } } @@ -426,7 +423,6 @@ int mlacp_sync_with_kernel_callback() if ((sys = system_get_instance()) == NULL) { - ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain System instance."); goto out; } @@ -607,9 +603,7 @@ int scheduler_prepare_session(struct CSM* csm) } else if (local_ip == peer_ip) { - ICCPD_LOG_WARN("connect", - "Sender IP is as the same as the peer IP. " - "This must be fixed before connection is built."); + ICCPD_LOG_WARN(__FUNCTION__, "Local IP must not be the same as the peer IP."); goto time_update; } diff --git a/src/iccpd/src/system.c b/src/iccpd/src/system.c index b6631d3be66f..9665b416ca52 100644 --- a/src/iccpd/src/system.c +++ b/src/iccpd/src/system.c @@ -38,6 +38,7 @@ struct System* system_get_instance() sys = (struct System*)malloc(sizeof(struct System)); if (sys == NULL ) { + ICCPD_LOG_WARN(__FUNCTION__, "Failed to obtain system instance."); return NULL; } system_init(sys); From bc194eaa5d53f7512fa24173b3dd6c1c77a3472b Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Thu, 24 Oct 2019 00:11:55 -0700 Subject: [PATCH 21/23] remove iccpd dependency with teamd Signed-off-by: shine.chen --- files/build_templates/iccpd.service.j2 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/files/build_templates/iccpd.service.j2 b/files/build_templates/iccpd.service.j2 index ef04f07696f7..979c45de72c5 100644 --- a/files/build_templates/iccpd.service.j2 +++ b/files/build_templates/iccpd.service.j2 @@ -1,7 +1,7 @@ [Unit] Description=ICCPD container -Requires=updategraph.service swss.service teamd.service -After=updategraph.service swss.service teamd.service +Requires=updategraph.service swss.service +After=updategraph.service swss.service [Service] User={{ sonicadmin_user }} @@ -10,4 +10,4 @@ ExecStart=/usr/bin/{{docker_container_name}}.sh wait ExecStop=/usr/bin/{{docker_container_name}}.sh stop [Install] -WantedBy=multi-user.target +WantedBy=multi-user.target swss.service From 0b089674b35a5f4a53bbbdc981a49bfd3a55799e Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Mon, 4 Nov 2019 18:53:20 -0800 Subject: [PATCH 22/23] print log level when dump mclag status Signed-off-by: shine.chen --- src/iccpd/include/logger.h | 1 + src/iccpd/src/iccp_cmd_show.c | 4 ++++ src/iccpd/src/logger.c | 2 +- src/iccpd/src/mclagdctl/mclagdctl.c | 9 +++++---- src/iccpd/src/mclagdctl/mclagdctl.h | 1 + 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/iccpd/include/logger.h b/src/iccpd/include/logger.h index d21e38d3727d..a90fece2a4d9 100644 --- a/src/iccpd/include/logger.h +++ b/src/iccpd/include/logger.h @@ -59,6 +59,7 @@ struct LoggerConfig struct LoggerConfig* logger_get_configuration(); void logger_set_configuration(int log_level); +char* log_level_to_string(int level); void log_setup(char* progname, char* path); void log_finalize(); void log_init(struct CmdOptionParser* parser); diff --git a/src/iccpd/src/iccp_cmd_show.c b/src/iccpd/src/iccp_cmd_show.c index 5b42de54bbb9..e25a653e74b3 100644 --- a/src/iccpd/src/iccp_cmd_show.c +++ b/src/iccpd/src/iccp_cmd_show.c @@ -40,6 +40,7 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) struct CSM *csm = NULL; struct LocalInterface *peer_link_if = NULL; struct LocalInterface *lif_po = NULL; + struct LoggerConfig* logconfig; char unknown[] = { "Unknown" }; int mclag_num = 0; int id_exist = 0; @@ -92,6 +93,9 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id) if (peer_link_if) memcpy(state_info.peer_link_mac, peer_link_if->mac_addr, 6); + logconfig = logger_get_configuration(); + memcpy(state_info.loglevel, log_level_to_string(logconfig->log_level), strlen( log_level_to_string(logconfig->log_level))); + state_info.role = csm->role_type; str_size = MCLAGDCTL_PORT_MEMBER_BUF_LEN; diff --git a/src/iccpd/src/logger.c b/src/iccpd/src/logger.c index 49c3a11393a8..2c17610f7afc 100644 --- a/src/iccpd/src/logger.c +++ b/src/iccpd/src/logger.c @@ -38,7 +38,7 @@ static uint32_t _iccpd_log_level_map[] = LOG_DEBUG, }; -static char* log_level_to_string(int level) +char* log_level_to_string(int level) { switch (level) { diff --git a/src/iccpd/src/mclagdctl/mclagdctl.c b/src/iccpd/src/mclagdctl/mclagdctl.c index 0396f5fa0a7a..7c5d7284066d 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.c +++ b/src/iccpd/src/mclagdctl/mclagdctl.c @@ -266,6 +266,7 @@ int mclagdctl_parse_dump_state(char *msg, int data_len) fprintf(stdout, "%s: %s\n", "MCLAG Interface", state_info->enabled_po); + fprintf(stdout, "%s: %s\n", "Loglevel", state_info->loglevel); } return 0; @@ -541,9 +542,9 @@ int mclagdctl_parse_config_loglevel(char *msg, int data_len) int ret = *(int*)msg; if (ret == 0) - fprintf(stdout, "%s\n", "Set mclag config debug level success!"); - else - fprintf(stdout, "%s\n", "Set mclag config debug level failed!"); + fprintf(stdout, "%s\n", "Config loglevel success!"); + else + fprintf(stdout, "%s\n", "Config loglevel failed!"); return 0; } @@ -706,7 +707,7 @@ int main(int argc, char **argv) char *data; struct mclagd_reply_hdr *reply; - while ((opt = getopt_long(argc, argv, "hil:", long_options, NULL)) >= 0) + while ((opt = getopt_long(argc, argv, "hi:l:", long_options, NULL)) >= 0) { switch (opt) { diff --git a/src/iccpd/src/mclagdctl/mclagdctl.h b/src/iccpd/src/mclagdctl/mclagdctl.h index 2c9a24d57ba1..1b8c6f278cc5 100644 --- a/src/iccpd/src/mclagdctl/mclagdctl.h +++ b/src/iccpd/src/mclagdctl/mclagdctl.h @@ -126,6 +126,7 @@ struct mclagd_state unsigned char peer_link_mac[MCLAGDCTL_ETHER_ADDR_LEN]; int role; char enabled_po[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; + char loglevel[MCLAGDCTL_PARA1_LEN]; }; struct mclagd_arp_msg From c4b60596301bf0b9aab62cc3fb910dc5a6622041 Mon Sep 17 00:00:00 2001 From: "shine.chen" Date: Sun, 29 Mar 2020 23:44:29 -0700 Subject: [PATCH 23/23] revise per community review Signed-off-by: shine.chen --- rules/config | 3 +++ rules/docker-iccpd.mk | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/rules/config b/rules/config index 31e5d40ff1f9..adc1e6b52152 100644 --- a/rules/config +++ b/rules/config @@ -95,3 +95,6 @@ FRR_USER_GID = 300 # Default VS build memory preparation DEFAULT_VS_PREPARE_MEM = yes + +# ENABLE_ICCPD - build docker-iccpd for mclag support +ENABLE_ICCPD = y diff --git a/rules/docker-iccpd.mk b/rules/docker-iccpd.mk index 3d79a2236b82..da661e9a2244 100644 --- a/rules/docker-iccpd.mk +++ b/rules/docker-iccpd.mk @@ -4,13 +4,15 @@ DOCKER_ICCPD = docker-iccpd.gz $(DOCKER_ICCPD)_PATH = $(DOCKERS_PATH)/docker-iccpd $(DOCKER_ICCPD)_DEPENDS += $(SWSS) $(REDIS_TOOLS) $(ICCPD) $(DOCKER_ICCPD)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_STRETCH) + +ifeq ($(ENABLE_ICCPD), y) SONIC_DOCKER_IMAGES += $(DOCKER_ICCPD) SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_ICCPD) - SONIC_STRETCH_DOCKERS += $(DOCKER_ICCPD) +endif $(DOCKER_ICCPD)_CONTAINER_NAME = iccpd -$(DOCKER_ICCPD)_RUN_OPT += --net=host --privileged -t +$(DOCKER_ICCPD)_RUN_OPT += --privileged -t $(DOCKER_ICCPD)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro $(DOCKER_ICCPD)_BASE_IMAGE_FILES += mclagdctl:/usr/bin/mclagdctl