diff --git a/dockers/docker-orchagent/Dockerfile.j2 b/dockers/docker-orchagent/Dockerfile.j2 index 9190a5d89b8f..097a582f6337 100755 --- a/dockers/docker-orchagent/Dockerfile.j2 +++ b/dockers/docker-orchagent/Dockerfile.j2 @@ -17,7 +17,8 @@ RUN apt-get update && \ libelf1 \ libmnl0 \ bridge-utils \ - conntrack + conntrack \ + ndppd {% if ( CONFIGURED_ARCH == "armhf" or CONFIGURED_ARCH == "arm64" ) %} ## Fix for gcc/python not found in arm docker @@ -60,6 +61,7 @@ RUN apt-get clean -y && \ COPY ["files/arp_update", "/usr/bin"] COPY ["arp_update.conf", "files/arp_update_vars.j2", "/usr/share/sonic/templates/"] +COPY ["ndppd.conf", "/usr/share/sonic/templates/"] COPY ["enable_counters.py", "/usr/bin"] COPY ["docker-init.sh", "orchagent.sh", "swssconfig.sh", "/usr/bin/"] COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] diff --git a/dockers/docker-orchagent/docker-init.sh b/dockers/docker-orchagent/docker-init.sh index 70b9f2d871b5..41d815b4d7a9 100755 --- a/dockers/docker-orchagent/docker-init.sh +++ b/dockers/docker-orchagent/docker-init.sh @@ -10,6 +10,7 @@ CFGGEN_PARAMS=" \ -t /usr/share/sonic/templates/ports.json.j2,/etc/swss/config.d/ports.json \ -t /usr/share/sonic/templates/copp.json.j2,/etc/swss/config.d/00-copp.config.json \ -t /usr/share/sonic/templates/vlan_vars.j2 \ + -t /usr/share/sonic/templates/ndppd.conf.j2,/etc/ndppd.conf \ " VLAN=$(sonic-cfggen $CFGGEN_PARAMS) @@ -18,9 +19,10 @@ if [ -x /usr/share/sonic/hwsku/hwsku-init ]; then /usr/share/sonic/hwsku/hwsku-init fi -# Start arp_update when VLAN exists +# Start arp_update and NDP proxy daemon when VLAN exists if [ "$VLAN" != "" ]; then cp /usr/share/sonic/templates/arp_update.conf /etc/supervisor/conf.d/ + cp /usr/share/sonic/templates/ndppd.conf /etc/supervisor/conf.d/ fi exec /usr/bin/supervisord diff --git a/dockers/docker-orchagent/ndppd.conf b/dockers/docker-orchagent/ndppd.conf new file mode 100644 index 000000000000..1e97bf97e313 --- /dev/null +++ b/dockers/docker-orchagent/ndppd.conf @@ -0,0 +1,9 @@ +[program:ndppd] +command=bash -c "/usr/sbin/ndppd | /usr/bin/logger" +priority=7 +autostart=false +autorestart=unexpected +stdout_logfile=syslog +stderr_logfile=syslog +dependent_startup=true +dependent_startup_wait_for=swssconfig:exited \ No newline at end of file diff --git a/dockers/docker-orchagent/ndppd.conf.j2 b/dockers/docker-orchagent/ndppd.conf.j2 new file mode 100644 index 000000000000..bc375f3c4987 --- /dev/null +++ b/dockers/docker-orchagent/ndppd.conf.j2 @@ -0,0 +1,37 @@ +{% block banner %} +# =========== Managed by sonic-cfggen -- DO NOT edit manually! ==================== +# Generated by /usr/share/sonic/templates/ndppd.conf.j2 using config DB data +# File: /etc/ndppd.conf +# +{% endblock banner %} +# Config file for ndppd, the NDP Proxy Daemon +# See man page for ndppd.conf.5 for descriptions of all available options +{% if VLAN_INTERFACE and VLAN_INTERFACE|pfx_filter|length > 0%} +{# Get all VLAN interfaces that have proxy_arp enabled #} +{% set proxy_interfaces = {} %} +{% for intf in VLAN_INTERFACE %} +{% if "proxy_arp" in VLAN_INTERFACE[intf] and VLAN_INTERFACE[intf]["proxy_arp"] == "enabled" %} +{% set _x = proxy_interfaces.update({intf: []}) %} +{% endif %} +{% endfor -%} + +{# Add each IPv6 prefix from each proxy_arp interface #} +{% for (intf, prefix) in VLAN_INTERFACE|pfx_filter %} +{% if intf in proxy_interfaces and prefix | ipv6 %} +{% set _x = proxy_interfaces[intf].append(prefix) %} +{% endif %} +{% endfor -%} + +{% for intf, prefix_list in proxy_interfaces.items() %} +{% if prefix_list %} + +proxy {{ intf }} { +{% for prefix in prefix_list %} + rule {{ prefix | network }}/{{ prefix | prefixlen }} { + static + } +{% endfor %} +} +{% endif %} +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules index bf5a4c9a50fe..3377688e6097 100755 --- a/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/debian/rules @@ -1,6 +1,6 @@ #!/usr/bin/make -f -PLATFORM = x86_64-accton_wedge100bf_32x-r0 +PLATFORM := x86_64-accton_wedge100bf_32x-r0 PACKAGE_NAME := sonic-platform-modules-bfn-montara SCRIPT_SRC := $(shell pwd)/scripts CONFIGS_SRC := $(shell pwd)/configs @@ -22,10 +22,10 @@ override_dh_auto_install: cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin dh_installdirs -p$(PACKAGE_NAME) etc/network/interfaces.d/ cp -r $(CONFIGS_SRC)/network/interfaces.d/* debian/$(PACKAGE_NAME)/etc/network/interfaces.d/ - dh_installdirs -p$(PACKAGE_NAME) /usr/share/sonic/device/${PLATFORM}/ - cp -r $(WHEEL_BUILD_DIR)/* debian/$(PACKAGE_NAME)/usr/share/sonic/device/${PLATFORM}/ - dh_installdirs -p$(PACKAGE_NAME) usr/share/sonic/device/${PLATFORM}/plugins - cp -r $(PLUGINS_DIR)/* debian/$(PACKAGE_NAME)/usr/share/sonic/device/${PLATFORM}/plugins/ + dh_installdirs -p$(PACKAGE_NAME) usr/share/sonic/device/$(PLATFORM)/ + cp -r $(WHEEL_BUILD_DIR)/* debian/$(PACKAGE_NAME)/usr/share/sonic/device/$(PLATFORM)/ + dh_installdirs -p$(PACKAGE_NAME) usr/share/sonic/device/$(PLATFORM)/plugins + cp -r $(PLUGINS_DIR)/* debian/$(PACKAGE_NAME)/usr/share/sonic/device/$(PLATFORM)/plugins/ override_dh_usrlocal: diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/chassis.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/chassis.py index 36a921d539f5..1ca885ff2a40 100644 --- a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/chassis.py +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/chassis.py @@ -24,7 +24,7 @@ def __init__(self): sfp_node = Sfp(index) self._sfp_list.append(sfp_node) - for i in range(MAX_PSU): + for i in range(1, MAX_PSU + 1): psu = Psu(i) self._psu_list.append(psu) diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py index a548e9364715..a1ebe5f224a9 100644 --- a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/eeprom.py @@ -2,7 +2,6 @@ try: - import time import os import sys import errno @@ -17,7 +16,7 @@ from sonic_eeprom import eeprom_base from sonic_eeprom import eeprom_tlvinfo - from .platform_thrift_client import ThriftClient + from .platform_thrift_client import thrift_try except ImportError, e: raise ImportError (str(e) + "- required module not found") @@ -65,8 +64,6 @@ EEPROM_STATUS = "/var/run/platform/eeprom/status" class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): - RETRIES = 35 - def __init__(self): with open(os.path.dirname(__file__) + "/logging.conf", 'r') as f: @@ -88,20 +85,16 @@ def __init__(self): self.eeprom_path = EEPROM_SYMLINK super(Eeprom, self).__init__(self.eeprom_path, 0, EEPROM_STATUS, True) - for attempt in range(self.RETRIES): - if self.eeprom_init(): - break - if attempt + 1 == self.RETRIES: - raise RuntimeError("eeprom.py: Initialization failed") - time.sleep(1) - - def eeprom_init(self): + def sys_eeprom_get(client): + return client.pltfm_mgr.pltfm_mgr_sys_eeprom_get() try: - with ThriftClient() as client: - self.eeprom = client.pltfm_mgr.pltfm_mgr_sys_eeprom_get() + self.eeprom = thrift_try(sys_eeprom_get) except Exception: - return False + raise RuntimeError("eeprom.py: Initialization failed") + + self.eeprom_parse() + def eeprom_parse(self): f = open(EEPROM_STATUS, 'w') f.write("ok") f.close() @@ -131,9 +124,13 @@ def eeprom_init(self): eeprom_params += "{0:s}={1:s}".format(elem[1], value) orig_stdout = sys.stdout + sys.stdout = StringIO() - new_e = eeprom_tlvinfo.TlvInfoDecoder.set_eeprom(self, "", [eeprom_params]) - sys.stdout = orig_stdout + try: + new_e = eeprom_tlvinfo.TlvInfoDecoder.set_eeprom(self, "", [eeprom_params]) + finally: + sys.stdout = orig_stdout + eeprom_base.EepromDecoder.write_eeprom(self, new_e) return True diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform_thrift_client.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform_thrift_client.py index 06afe8e962ae..96c0e09ba1c0 100644 --- a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform_thrift_client.py +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/platform_thrift_client.py @@ -3,6 +3,7 @@ try: import os import sys + import time import importlib sys.path.append(os.path.dirname(__file__)) @@ -11,6 +12,7 @@ from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from thrift.protocol import TMultiplexedProtocol + from thrift.Thrift import TException except ImportError as e: raise ImportError (str(e) + "- required module not found") @@ -35,3 +37,13 @@ def __enter__(self): return self.open() def __exit__(self, exc_type, exc_value, tb): self.close() + +def thrift_try(func, attempts=35): + for attempt in range(attempts): + try: + with ThriftClient() as client: + return func(client) + except TException as e: + if attempt + 1 == attempts: + raise e + time.sleep(1) diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/psu.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/psu.py index 33adad8c1ac6..7e7e4403ad5c 100644 --- a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/psu.py +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/psu.py @@ -6,7 +6,7 @@ sys.path.append(os.path.dirname(__file__)) - from .platform_thrift_client import ThriftClient + from .platform_thrift_client import thrift_try from sonic_platform_base.psu_base import PsuBase except ImportError as e: @@ -34,9 +34,11 @@ def get_powergood_status(self): :param self.index: An integer, 1-based self.index of the PSU of which to query status :return: Boolean, True if PSU is operating properly, False if PSU is faulty """ + def psu_info_get(client): + return client.pltfm_mgr.pltfm_mgr_pwr_supply_info_get(self.index) + try: - with ThriftClient() as client: - psu_info = client.pltfm_mgr.pltfm_mgr_pwr_supply_info_get(self.index) + psu_info = thrift_try(psu_info_get) except Exception: return False @@ -49,9 +51,11 @@ def get_presence(self): :param self.index: An integer, 1-based self.index of the PSU of which to query status :return: Boolean, True if PSU is plugged, False if not """ + def psu_present_get(client): + return client.pltfm_mgr.pltfm_mgr_pwr_supply_present_get(self.index) + try: - with ThriftClient() as client: - status = client.pltfm_mgr.pltfm_mgr_pwr_supply_present_get(self.index) + status = thrift_try(psu_present_get) except Exception: return False diff --git a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/sfp.py b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/sfp.py index 1b63630d1a8f..12587c66f474 100644 --- a/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/sfp.py +++ b/platform/barefoot/sonic-platform-modules-bfn-montara/sonic_platform/sfp.py @@ -8,6 +8,7 @@ sys.path.append(os.path.dirname(__file__)) from .platform_thrift_client import ThriftClient + from .platform_thrift_client import thrift_try from sonic_platform_base.sfp_base import SfpBase from sonic_platform_base.sonic_sfp.sfputilbase import SfpUtilBase @@ -65,11 +66,13 @@ def __init__(self): SfpUtilBase.__init__(self) def update_port_info(self): + def qsfp_max_port_get(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_get_max_port(); + if self.QSFP_PORT_END == 0: - with ThriftClient() as client: - self.QSFP_PORT_END = client.pltfm_mgr.pltfm_mgr_qsfp_get_max_port(); - self.PORT_END = self.QSFP_PORT_END - self.PORTS_IN_BLOCK = self.QSFP_PORT_END + self.QSFP_PORT_END = thrift_try(qsfp_max_port_get) + self.PORT_END = self.QSFP_PORT_END + self.PORTS_IN_BLOCK = self.QSFP_PORT_END def get_presence(self, port_num): # Check for invalid port_num @@ -78,9 +81,11 @@ def get_presence(self, port_num): presence = False + def qsfp_presence_get(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_presence_get(port_num) + try: - with ThriftClient() as client: - presence = client.pltfm_mgr.pltfm_mgr_qsfp_presence_get(port_num) + presence = thrift_try(qsfp_presence_get) except Exception as e: print e.__doc__ print e.message @@ -92,8 +97,11 @@ def get_low_power_mode(self, port_num): if port_num < self.port_start or port_num > self.port_end: return False - with ThriftClient() as client: - lpmode = client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_get(port_num) + def qsfp_lpmode_get(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_get(port_num) + + lpmode = thrift_try(qsfp_lpmode_get) + return lpmode def set_low_power_mode(self, port_num, lpmode): @@ -101,8 +109,11 @@ def set_low_power_mode(self, port_num, lpmode): if port_num < self.port_start or port_num > self.port_end: return False - with ThriftClient() as client: - status = client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_set(port_num, lpmode) + def qsfp_lpmode_set(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_set(port_num, lpmode) + + status = thrift_try(qsfp_lpmode_set) + return (status == 0) def reset(self, port_num): @@ -110,9 +121,12 @@ def reset(self, port_num): if port_num < self.port_start or port_num > self.port_end: return False - with ThriftClient() as client: + def qsfp_reset(client): client.pltfm_mgr.pltfm_mgr_qsfp_reset(port_num, True) - status = client.pltfm_mgr.pltfm_mgr_qsfp_reset(port_num, False) + return client.pltfm_mgr.pltfm_mgr_qsfp_reset(port_num, False) + + status = thrift_try(qsfp_reset) + return status def check_transceiver_change(self): @@ -188,15 +202,16 @@ def get_transceiver_change_event(self, timeout=0): def _get_port_eeprom_path(self, port_num, devid): eeprom_path = None - with ThriftClient() as client: - presence = client.pltfm_mgr.pltfm_mgr_qsfp_presence_get(port_num) - if presence == True: - eeprom_cache = open(SFP_EEPROM_CACHE, 'wb') - eeprom_hex = client.pltfm_mgr.pltfm_mgr_qsfp_info_get(port_num) - eeprom_raw = bytearray.fromhex(eeprom_hex) - eeprom_cache.write(eeprom_raw) - eeprom_cache.close() - eeprom_path = SFP_EEPROM_CACHE + def qsfp_info_get(client): + return client.pltfm_mgr.pltfm_mgr_qsfp_info_get(port_num) + + if self.get_presence(port_num): + eeprom_hex = thrift_try(qsfp_info_get) + eeprom_cache = open(SFP_EEPROM_CACHE, 'wb') + eeprom_raw = bytearray.fromhex(eeprom_hex) + eeprom_cache.write(eeprom_raw) + eeprom_cache.close() + eeprom_path = SFP_EEPROM_CACHE return eeprom_path diff --git a/platform/barefoot/sonic-platform-modules-bfn/debian/rules b/platform/barefoot/sonic-platform-modules-bfn/debian/rules index 1bea5b4c67ef..37e264ad7ed8 100755 --- a/platform/barefoot/sonic-platform-modules-bfn/debian/rules +++ b/platform/barefoot/sonic-platform-modules-bfn/debian/rules @@ -20,8 +20,6 @@ override_dh_auto_install: cp -r $(SCRIPT_SRC)/* debian/$(PACKAGE_NAME)/usr/local/bin dh_installdirs -p$(PACKAGE_NAME) etc/network/interfaces.d/ cp -r $(CONFIGS_SRC)/network/interfaces.d/* debian/$(PACKAGE_NAME)/etc/network/interfaces.d/ - dh_installdirs -p$(PACKAGE_NAME) usr/share/sonic/platform/ - cp -r $(WHEEL_BUILD_DIR)/* debian/$(PACKAGE_NAME)/usr/share/sonic/platform/ override_dh_usrlocal: diff --git a/src/sonic-config-engine/tests/data/ndppd/vlan_interfaces.json b/src/sonic-config-engine/tests/data/ndppd/vlan_interfaces.json new file mode 100644 index 000000000000..d45214827642 --- /dev/null +++ b/src/sonic-config-engine/tests/data/ndppd/vlan_interfaces.json @@ -0,0 +1,20 @@ +{ + "VLAN_INTERFACE": { + "Vlan1000": { + "proxy_arp": "enabled" + }, + "Vlan1000|192.168.0.1/21": {}, + "Vlan1000|fc01:1000::1/64": {}, + "Vlan1000|fc02:1000::1/64": {}, + "Vlan1000|fc03:1000::1/64": {}, + "Vlan2000": { + "proxy_arp": "enabled" + }, + "Vlan2000|fc01:2000::1/64": {}, + "Vlan3000|fc01:3000::1/64": {}, + "Vlan4000": { + "proxy_arp": "disabled" + }, + "Vlan4000|fc01:4000::1/64": {} + } +} \ No newline at end of file diff --git a/src/sonic-config-engine/tests/ndppd.conf.j2 b/src/sonic-config-engine/tests/ndppd.conf.j2 new file mode 120000 index 000000000000..e6f2f543eee4 --- /dev/null +++ b/src/sonic-config-engine/tests/ndppd.conf.j2 @@ -0,0 +1 @@ +../../../dockers/docker-orchagent/ndppd.conf.j2 \ No newline at end of file diff --git a/src/sonic-config-engine/tests/sample_output/py2/ndppd.conf b/src/sonic-config-engine/tests/sample_output/py2/ndppd.conf new file mode 100644 index 000000000000..71ff1dfaf9ca --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py2/ndppd.conf @@ -0,0 +1,25 @@ +# =========== Managed by sonic-cfggen -- DO NOT edit manually! ==================== +# Generated by /usr/share/sonic/templates/ndppd.conf.j2 using config DB data +# File: /etc/ndppd.conf +# +# Config file for ndppd, the NDP Proxy Daemon +# See man page for ndppd.conf.5 for descriptions of all available options + +proxy Vlan1000 { + rule fc02:1000::/64 { + static + } + rule fc03:1000::/64 { + static + } + rule fc01:1000::/64 { + static + } +} + +proxy Vlan2000 { + rule fc01:2000::/64 { + static + } +} + diff --git a/src/sonic-config-engine/tests/sample_output/py3/ndppd.conf b/src/sonic-config-engine/tests/sample_output/py3/ndppd.conf new file mode 100644 index 000000000000..28a239006d24 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/py3/ndppd.conf @@ -0,0 +1,25 @@ +# =========== Managed by sonic-cfggen -- DO NOT edit manually! ==================== +# Generated by /usr/share/sonic/templates/ndppd.conf.j2 using config DB data +# File: /etc/ndppd.conf +# +# Config file for ndppd, the NDP Proxy Daemon +# See man page for ndppd.conf.5 for descriptions of all available options + +proxy Vlan1000 { + rule fc01:1000::/64 { + static + } + rule fc02:1000::/64 { + static + } + rule fc03:1000::/64 { + static + } +} + +proxy Vlan2000 { + rule fc01:2000::/64 { + static + } +} + diff --git a/src/sonic-config-engine/tests/test_j2files.py b/src/sonic-config-engine/tests/test_j2files.py index 98bb2437628d..ad06f61b84c5 100644 --- a/src/sonic-config-engine/tests/test_j2files.py +++ b/src/sonic-config-engine/tests/test_j2files.py @@ -171,6 +171,16 @@ def test_ipinip_multi_asic(self): sample_output_file = os.path.join(self.test_dir, 'multi_npu_data', utils.PYvX_DIR, 'ipinip.json') assert filecmp.cmp(sample_output_file, self.output_file) + def test_ndppd_conf(self): + conf_template = os.path.join(self.test_dir, "ndppd.conf.j2") + vlan_interfaces_json = os.path.join(self.test_dir, "data", "ndppd", "vlan_interfaces.json") + expected = os.path.join(self.test_dir, "sample_output", utils.PYvX_DIR, "ndppd.conf") + + argument = '-j {} -t {} > {}'.format(vlan_interfaces_json, conf_template, self.output_file) + self.run_script(argument) + assert filecmp.cmp(expected, self.output_file), self.run_diff(expected, self.output_file) + + def tearDown(self): try: os.remove(self.output_file)