diff --git a/.gitignore b/.gitignore
index b75083ce4d57..74998573e491 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ dockers/docker-router-advertiser/Dockerfile
dockers/docker-snmp-sv2/Dockerfile
dockers/docker-teamd/Dockerfile
dockers/docker-sonic-mgmt/Dockerfile
+dockers/docker-sonic-telemetry/Dockerfile
platform/*/docker-syncd-*/Dockerfile
platform/*/docker-syncd-*-rpc/Dockerfile
platform/vs/docker-sonic-vs/Dockerfile
diff --git a/Makefile b/Makefile
index ed0c853e22df..6471f7f757b9 100644
--- a/Makefile
+++ b/Makefile
@@ -70,7 +70,8 @@ SONIC_BUILD_INSTRUCTION := make \
USERNAME=$(USERNAME) \
SONIC_BUILD_JOBS=$(SONIC_BUILD_JOBS) \
HTTP_PROXY=$(http_proxy) \
- HTTPS_PROXY=$(https_proxy)
+ HTTPS_PROXY=$(https_proxy) \
+ ENABLE_SYSTEM_TELEMETRY=$(ENABLE_SYSTEM_TELEMETRY)
.PHONY: sonic-slave-build sonic-slave-bash init reset
diff --git a/device/accton/x86_64-accton_as5712_54x-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as5712_54x-r0/plugins/psuutil.py
new file mode 100755
index 000000000000..841070637b3e
--- /dev/null
+++ b/device/accton/x86_64-accton_as5712_54x-r0/plugins/psuutil.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Accton
+#
+# Module contains an implementation of SONiC PSU Base API and
+# provides the PSUs status which are available in the platform
+#
+#############################################################################
+
+import os.path
+
+try:
+ from sonic_psu.psu_base import PsuBase
+except ImportError as e:
+ raise ImportError (str(e) + "- required module not found")
+
+class PsuUtil(PsuBase):
+ """Platform-specific PSUutil class"""
+
+ def __init__(self):
+ PsuBase.__init__(self)
+
+ self.psu_path = "/sys/bus/i2c/devices/"
+ self.psu_presence = "/psu_present"
+ self.psu_oper_status = "/psu_power_good"
+ self.psu_mapping = {
+ 1: "57-0038",
+ 2: "58-003b",
+ }
+
+ def get_num_psus(self):
+ return len(self.psu_mapping)
+
+ def get_psu_status(self, index):
+ if index is None:
+ return False
+
+ status = 0
+ node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status
+ try:
+ with open(node, 'r') as power_status:
+ status = int(power_status.read())
+ except IOError:
+ return False
+
+ return status == 1
+
+ def get_psu_presence(self, index):
+ if index is None:
+ return False
+
+ status = 0
+ node = self.psu_path + self.psu_mapping[index] + self.psu_presence
+ try:
+ with open(node, 'r') as presence_status:
+ status = int(presence_status.read())
+ except IOError:
+ return False
+
+ return status == 1
diff --git a/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py
index d554910ac5cd..c30ba62c51bd 100755
--- a/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py
+++ b/device/accton/x86_64-accton_as5712_54x-r0/plugins/sfputil.py
@@ -20,84 +20,87 @@ class SfpUtil(SfpUtilBase):
QSFP_PORT_END = 72
BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/"
+ BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/"
+ BASE_CPLD2_PATH = "/sys/bus/i2c/devices/0-0061/"
+ BASE_CPLD3_PATH = "/sys/bus/i2c/devices/0-0062/"
_port_to_is_present = {}
_port_to_lp_mode = {}
_port_to_eeprom_mapping = {}
_port_to_i2c_mapping = {
- 0: [2, 2],
- 1: [3, 3],
- 2: [4, 4],
- 3: [5, 5],
- 4: [6, 6],
- 5: [7, 7],
- 6: [8, 8],
- 7: [9, 9],
- 8: [10, 10],
- 9: [11, 11],
- 10: [12, 12],
- 11: [13, 13],
- 12: [14, 14],
- 13: [15, 15],
- 14: [16, 16],
- 15: [17, 17],
- 16: [18, 18],
- 17: [19, 19],
- 18: [20, 20],
- 19: [21, 21],
- 20: [22, 22],
- 21: [23, 23],
- 22: [24, 24],
- 23: [25, 25],
- 24: [26, 26],
- 25: [27, 27],
- 26: [28, 28],
- 27: [29, 29],
- 28: [30, 30],
- 29: [31, 31],
- 30: [32, 32],
- 31: [33, 33],
- 32: [34, 34],
- 33: [35, 35],
- 34: [36, 36],
- 35: [37, 37],
- 36: [38, 38],
- 37: [39, 39],
- 38: [40, 40],
- 39: [41, 41],
- 40: [42, 42],
- 41: [43, 43],
- 42: [44, 44],
- 43: [45, 45],
- 44: [46, 46],
- 45: [47, 47],
- 46: [48, 48],
- 47: [49, 49],
- 48: [50, 50], #QSFP49
- 49: [50, 50],
- 50: [50, 50],
- 51: [50, 50],
- 52: [52, 52], #QSFP50
- 53: [52, 52],
- 54: [52, 52],
- 55: [52, 52],
- 56: [54, 54], #QSFP51
- 57: [54, 54],
- 58: [54, 54],
- 59: [54, 54],
- 60: [51, 51], #QSFP52
- 61: [51, 51],
- 62: [51, 51],
- 63: [51, 51],
+ 0: [1, 2],
+ 1: [2, 3],
+ 2: [3, 4],
+ 3: [4, 5],
+ 4: [5, 6],
+ 5: [6, 7],
+ 6: [7, 8],
+ 7: [8, 9],
+ 8: [9, 10],
+ 9: [10, 11],
+ 10: [11, 12],
+ 11: [12, 13],
+ 12: [13, 14],
+ 13: [14, 15],
+ 14: [15, 16],
+ 15: [16, 17],
+ 16: [17, 18],
+ 17: [18, 19],
+ 18: [19, 20],
+ 19: [20, 21],
+ 20: [21, 22],
+ 21: [22, 23],
+ 22: [23, 24],
+ 23: [24, 25],
+ 24: [25, 26],
+ 25: [26, 27],
+ 26: [27, 28],
+ 27: [28, 29],
+ 28: [29, 30],
+ 29: [30, 31],
+ 30: [31, 32],
+ 31: [32, 33],
+ 32: [33, 34],
+ 33: [34, 35],
+ 34: [35, 36],
+ 35: [36, 37],
+ 36: [37, 38],
+ 37: [38, 39],
+ 38: [39, 40],
+ 39: [40, 41],
+ 40: [41, 42],
+ 41: [42, 43],
+ 42: [43, 44],
+ 43: [44, 45],
+ 44: [45, 46],
+ 45: [46, 47],
+ 46: [47, 48],
+ 47: [48, 49],
+ 48: [49, 50],#QSFP49
+ 49: [49, 50],
+ 50: [49, 50],
+ 51: [49, 50],
+ 52: [50, 52],#QSFP50
+ 53: [50, 52],
+ 54: [50, 52],
+ 55: [50, 52],
+ 56: [51, 54],#QSFP51
+ 57: [51, 54],
+ 58: [51, 54],
+ 59: [51, 54],
+ 60: [52, 51],#QSFP52
+ 61: [52, 51],
+ 62: [52, 51],
+ 63: [52, 51],
64: [53, 53], #QSFP53
65: [53, 53],
66: [53, 53],
67: [53, 53],
- 68: [55, 55], #QSFP54
- 69: [55, 55],
- 70: [55, 55],
- 71: [55, 55],
+ 68: [54, 55],#QSFP54
+ 69: [54, 55],
+ 70: [54, 55],
+ 71: [54, 55],
}
@property
@@ -125,12 +128,12 @@ def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping
def __init__(self):
- eeprom_path = self.BASE_VAL_PATH + "sfp_eeprom"
+ eeprom_path = self.BASE_OOM_PATH + "eeprom"
for x in range(0, self.port_end+1):
self.port_to_eeprom_mapping[x] = eeprom_path.format(
- self._port_to_i2c_mapping[x][0],
- self._port_to_i2c_mapping[x][1])
+ self._port_to_i2c_mapping[x][1]
+ )
SfpUtilBase.__init__(self)
@@ -139,8 +142,13 @@ def get_presence(self, port_num):
if port_num < self.port_start or port_num > self.port_end:
return False
- present_path = self.BASE_VAL_PATH + "sfp_is_present"
- self.__port_to_is_present = present_path.format(self._port_to_i2c_mapping[port_num][0], self._port_to_i2c_mapping[port_num][1])
+ if port_num < 24:
+ present_path = self.BASE_CPLD2_PATH + "module_present_" + str(self._port_to_i2c_mapping[port_num][0])
+ else:
+ present_path = self.BASE_CPLD3_PATH + "module_present_" + str(self._port_to_i2c_mapping[port_num][0])
+
+ self.__port_to_is_present = present_path
+
try:
val_file = open(self.__port_to_is_present)
@@ -161,11 +169,10 @@ def get_low_power_mode(self, port_num):
if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
return False
- lp_mode_path = self.BASE_VAL_PATH + "sfp_lp_mode"
- self.__port_to_lp_mode = lp_mode_path.format(self._port_to_i2c_mapping[port_num][0], self._port_to_i2c_mapping[port_num][1])
+ lp_mode_path = self.BASE_CPLD3_PATH + "module_lp_mode_" + str(self._port_to_i2c_mapping[port_num][0])
try:
- val_file = open(self.__port_to_lp_mode)
+ val_file = open(lp_mode_path)
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
@@ -183,11 +190,10 @@ def set_low_power_mode(self, port_num, lpmode):
if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
return False
- lp_mode_path = self.BASE_VAL_PATH + "sfp_lp_mode"
- self.__port_to_lp_mode = lp_mode_path.format(self._port_to_i2c_mapping[port_num][0], self._port_to_i2c_mapping[port_num][1])
+ lp_mode_path = self.BASE_CPLD3_PATH + "module_lp_mode_" + str(self._port_to_i2c_mapping[port_num][0])
try:
- reg_file = open(self.__port_to_lp_mode, 'r+')
+ reg_file = open(lp_mode_path, 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
@@ -206,10 +212,10 @@ def reset(self, port_num):
if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
return False
- mod_rst_path = self.BASE_VAL_PATH + "sfp_mod_rst"
- self.__port_to_mod_rst = mod_rst_path.format(self._port_to_i2c_mapping[port_num][0], self._port_to_i2c_mapping[port_num][1])
+ mod_rst_path = lp_mode_path = self.BASE_CPLD3_PATH + "module_reset_" + str(self._port_to_i2c_mapping[port_num][0])
+
try:
- reg_file = open(self.__port_to_mod_rst, 'r+')
+ reg_file = open(mod_rst_path, 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
diff --git a/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf b/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf
index a8fef6185912..107095cdad7c 100644
--- a/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf
+++ b/device/dell/x86_64-dell_s6000_s1220-r0/installer.conf
@@ -5,8 +5,8 @@ if [ "$install_env" = "onie" ]; then
echo "Replace ONIE reboot with Dell reset commands"
# set I2C GPIO mux
-echo 1 > /sys/class/gpio/export
-echo 2 > /sys/class/gpio/export
+[ -d /sys/class/gpio/gpio1 ] || echo 1 > /sys/class/gpio/export
+[ -d /sys/class/gpio/gpio2 ] || echo 2 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio1/direction
echo out > /sys/class/gpio/gpio2/direction
echo 0 > /sys/class/gpio/gpio1/value
diff --git a/dockers/docker-fpm-quagga/supervisord.conf b/dockers/docker-fpm-quagga/supervisord.conf
index 92d806ff281c..3e05215babaa 100644
--- a/dockers/docker-fpm-quagga/supervisord.conf
+++ b/dockers/docker-fpm-quagga/supervisord.conf
@@ -8,6 +8,7 @@ command=/usr/bin/start.sh
priority=1
autostart=true
autorestart=false
+startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
@@ -16,6 +17,7 @@ command=/usr/bin/bgpcfgd
priority=2
autostart=false
autorestart=false
+startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
@@ -24,6 +26,7 @@ command=/usr/sbin/rsyslogd -n
priority=3
autostart=false
autorestart=false
+startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
@@ -32,6 +35,7 @@ command=/usr/lib/quagga/zebra -A 127.0.0.1
priority=4
autostart=false
autorestart=false
+startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
@@ -40,6 +44,7 @@ command=/usr/lib/quagga/bgpd -A 127.0.0.1 -F
priority=5
autostart=false
autorestart=false
+startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
@@ -48,5 +53,6 @@ command=fpmsyncd
priority=6
autostart=false
autorestart=false
+startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
diff --git a/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf b/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf
index 08a3e0a94872..f0bb4d5b3bbd 100644
--- a/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf
+++ b/dockers/docker-router-advertiser/docker-router-advertiser.supervisord.conf
@@ -8,6 +8,7 @@ command=/usr/bin/start.sh
priority=1
autostart=true
autorestart=false
+startsecs=0
stdout_logfile=syslog
stderr_logfile=syslog
diff --git a/dockers/docker-router-advertiser/start.sh b/dockers/docker-router-advertiser/start.sh
index cbd5ec383bd6..7fcaf65a79c9 100755
--- a/dockers/docker-router-advertiser/start.sh
+++ b/dockers/docker-router-advertiser/start.sh
@@ -1,11 +1,18 @@
#!/usr/bin/env bash
-# Generate /etc/radvd.conf config file
-sonic-cfggen -d -t /usr/share/sonic/templates/radvd.conf.j2 > /etc/radvd.conf
-
rm -f /var/run/rsyslogd.pid
supervisorctl start rsyslogd
+# Router advertiser should only run on ToR (T0) devices
+DEVICE_ROLE=$(sonic-cfggen -d -v "DEVICE_METADATA.localhost.type")
+if [ "$DEVICE_ROLE" != "ToRRouter" ]; then
+ echo "Device role is not ToRRouter. Not starting router advertiser process."
+ exit 0
+fi
+
+# Generate /etc/radvd.conf config file
+sonic-cfggen -d -t /usr/share/sonic/templates/radvd.conf.j2 > /etc/radvd.conf
+
# Start the router advertiser
supervisorctl start radvd
diff --git a/dockers/docker-sonic-telemetry/Dockerfile.j2 b/dockers/docker-sonic-telemetry/Dockerfile.j2
new file mode 100644
index 000000000000..bbb15db69aaa
--- /dev/null
+++ b/dockers/docker-sonic-telemetry/Dockerfile.j2
@@ -0,0 +1,31 @@
+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
+
+COPY \
+{% for deb in docker_sonic_telemetry_debs.split(' ') -%}
+debs/{{ deb }}{{' '}}
+{%- endfor -%}
+debs/
+
+RUN dpkg -i \
+{% for deb in docker_sonic_telemetry_debs.split(' ') -%}
+debs/{{ deb }}{{' '}}
+{%- endfor %}
+
+COPY ["start.sh", "telemetry.sh", "dialout.sh", "/usr/bin/"]
+COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
+
+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-sonic-telemetry/dialout.sh b/dockers/docker-sonic-telemetry/dialout.sh
new file mode 100755
index 000000000000..8683e8edae8e
--- /dev/null
+++ b/dockers/docker-sonic-telemetry/dialout.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+# Start with default config
+
+exec /usr/sbin/dialout_client_cli -insecure -logtostderr -v 2
+
diff --git a/dockers/docker-sonic-telemetry/start.sh b/dockers/docker-sonic-telemetry/start.sh
new file mode 100755
index 000000000000..b307e387d557
--- /dev/null
+++ b/dockers/docker-sonic-telemetry/start.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+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 telemetry
+supervisorctl start dialout
diff --git a/dockers/docker-sonic-telemetry/supervisord.conf b/dockers/docker-sonic-telemetry/supervisord.conf
new file mode 100644
index 000000000000..dcd8a9eb1e80
--- /dev/null
+++ b/dockers/docker-sonic-telemetry/supervisord.conf
@@ -0,0 +1,36 @@
+[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:telemetry]
+command=/usr/bin/telemetry.sh
+priority=3
+autostart=false
+autorestart=true
+stdout_logfile=syslog
+stderr_logfile=syslog
+
+[program:dialout]
+command=/usr/bin/dialout.sh
+priority=4
+autostart=false
+autorestart=true
+stdout_logfile=syslog
+stderr_logfile=syslog
diff --git a/dockers/docker-sonic-telemetry/telemetry.sh b/dockers/docker-sonic-telemetry/telemetry.sh
new file mode 100755
index 000000000000..053b1dae6ead
--- /dev/null
+++ b/dockers/docker-sonic-telemetry/telemetry.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+
+# Try to read telemetry and x509 config from ConfigDB.
+# Use default value if no valid config exists
+X509=`sonic-cfggen -d -v "DEVICE_METADATA['x509']"`
+TELEMETRY=`sonic-cfggen -d -v 'TELEMETRY.keys() | join(" ") if TELEMETRY'`
+
+TELEMETRY_ARGS=" -logtostderr"
+
+if [ ! -z $X509 ]; then
+ SERVER_CRT=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['server_crt']"`
+ SERVER_KEY=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['server_key']"`
+ if [ -z $SERVER_CRT ] || [ -z $SERVER_KEY ]; then
+ TELEMETRY_ARGS+=" --insecure"
+ else
+ TELEMETRY_ARGS+=" --server_crt $SERVER_CRT --server_key $SERVER_KEY "
+ fi
+else
+ TELEMETRY_ARGS+=" --insecure"
+fi
+
+if [ ! -z $X509 ]; then
+ CA_CRT=`sonic-cfggen -d -v "DEVICE_METADATA['x509']['ca_crt']"`
+ if [ ! -z $CA_CRT ]; then
+ TELEMETRY_ARGS+=" --ca_crt $CA_CRT"
+ fi
+fi
+
+# If no configuration entry exists for TELEMETRY, create one default port
+if [ -z $TELEMETRY ]; then
+ redis-cli -n 4 hset "TELEMETRY|gnmi" port 8080
+fi
+
+PORT=`sonic-cfggen -d -v "TELEMETRY['gnmi']['port']"`
+TELEMETRY_ARGS+=" --port $PORT"
+
+CLIENT_AUTH=`sonic-cfggen -d -v "TELEMETRY['gnmi']['client_auth']"`
+if [ -z $CLIENT_AUTH ] || [ $CLIENT_AUTH == "false" ]; then
+ TELEMETRY_ARGS+=" --allow_no_client_auth"
+fi
+
+LOG_LEVEL=`sonic-cfggen -d -v "TELEMETRY['gnmi']['log_level']"`
+if [ ! -z $LOG_LEVEL ]; then
+ TELEMETRY_ARGS+=" -v=$LOG_LEVEL"
+else
+ TELEMETRY_ARGS+=" -v=2"
+fi
+
+exec /usr/sbin/telemetry ${TELEMETRY_ARGS}
+
+
diff --git a/files/Aboot/boot0.j2 b/files/Aboot/boot0.j2
index 435781a77485..5ed75852cb93 100644
--- a/files/Aboot/boot0.j2
+++ b/files/Aboot/boot0.j2
@@ -206,8 +206,7 @@ write_boot_configs() {
elif [ ! -f "$cmdline_base" ]; then
# some systems were started with other versions of this script and therefore
# do not have the $cmdline_base file. we assume that we are on Sonic or EOS.
- cat /proc/cmdline > $cmdline_base
- sed -Ei 's/^(.*) rw .*$/\1/' $cmdline_base
+ cat /proc/cmdline | sed -E 's/^(.*) rw .*$/\1/' | tr ' ' '\n' > $cmdline_base
fi
cp $cmdline_base /tmp/append
@@ -215,6 +214,10 @@ write_boot_configs() {
platform_specific
echo "rw loop=$image_name/fs.squashfs loopfstype=squashfs apparmor=1 security=apparmor quiet" >> /tmp/append
+ # Pass the MAC address to the new kernel as a command line parameter. This makes it
+ # possible to restore the MAC address in the new kernel without requiring driver modifications.
+ [ "${NETDEV}" ] || NETDEV=ma1
+ echo "hwaddr_${NETDEV}=$(cat /sys/class/net/${NETDEV}/address)" >> /tmp/append
# use extra parameters from kernel-params hook if the file exists
if [ -f "$target_path/$kernel_params" ]; then
diff --git a/files/build_templates/docker_image_ctl.j2 b/files/build_templates/docker_image_ctl.j2
index 6592e9ed173d..b17c70b4a9d2 100644
--- a/files/build_templates/docker_image_ctl.j2
+++ b/files/build_templates/docker_image_ctl.j2
@@ -63,6 +63,13 @@ start() {
docker run -d {{docker_image_run_opt}} \
{%- if '--log-driver=json-file' in docker_image_run_opt or '--log-driver' not in docker_image_run_opt %}
--log-opt max-size=2M --log-opt max-file=5 \
+{%- endif %}
+{%- if docker_container_name == "syncd" and sonic_asic_platform == "mellanox" %}
+ -e SX_SNIFFER_ENABLE \
+ -e SX_SNIFFER_TARGET \
+ -e PRM_SNIFFER \
+ -e PRM_SNIFFER_FILE_PATH \
+ -v /var/log/mellanox/sniffer:/var/log/mellanox/sniffer:rw \
{%- endif %}
-v /var/run/redis:/var/run/redis:rw \
-v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \
diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2
index 91ee8519e83e..0849118b83a4 100644
--- a/files/build_templates/sonic_debian_extension.j2
+++ b/files/build_templates/sonic_debian_extension.j2
@@ -165,7 +165,11 @@ sudo bash -c "echo dhcp_as_static=true >> $FILESYSTEM_ROOT/etc/sonic/updategraph
{% else %}
sudo bash -c "echo enabled=false > $FILESYSTEM_ROOT/etc/sonic/updategraph.conf"
{% endif %}
-sudo bash -c "echo '{ \"DEVICE_METADATA\": { \"localhost\": { \"default_bgp_status\": {% if shutdown_bgp_on_start == "y" %}\"down\"{% else %}\"up\"{% endif %}, \"default_pfcwd_status\": {% if enable_pfcwd_on_start == "y" %}\"enable\"{% else %}\"disable\"{% endif %} } } }' >> $FILESYSTEM_ROOT/etc/sonic/init_cfg.json"
+sudo bash -c "echo '{ \"DEVICE_METADATA\": { \"localhost\": { \"default_bgp_status\": {% if shutdown_bgp_on_start == "y" %}\"down\"{% else %}\"up\"{% endif %}, \"default_pfcwd_status\": {% if enable_pfcwd_on_start == "y" %}\"enable\"{% else %}\"disable\"{% endif %} } },
+{%- print ' \\"CRM\\": { \\"Config\\": { \\"polling_interval\\": \\"300\\", ' %}
+{%- for crm_res in ["ipv4_route", "ipv6_route", "ipv4_nexthop", "ipv6_nexthop", "ipv4_neighbor", "ipv6_neighbor", "nexthop_group_member", "nexthop_group", "acl_table", "acl_group", "acl_entry", "acl_counter", "fdb_entry"] -%}
+\"{{crm_res}}_threshold_type\": \"percentage\", \"{{crm_res}}_low_threshold\": \"70\", \"{{crm_res}}_high_threshold\": \"85\"{% if not loop.last %}, {% endif %}
+{%- endfor %} } } }' >> $FILESYSTEM_ROOT/etc/sonic/init_cfg.json"
# Copy SNMP configuration files
sudo cp $IMAGE_CONFIGS/snmp/snmp.yml $FILESYSTEM_ROOT/etc/sonic/
diff --git a/files/build_templates/telemetry.service.j2 b/files/build_templates/telemetry.service.j2
new file mode 100644
index 000000000000..5f2e81ed95ea
--- /dev/null
+++ b/files/build_templates/telemetry.service.j2
@@ -0,0 +1,13 @@
+[Unit]
+Description=Telemetry container
+Requires=swss.service
+After=swss.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/files/image_config/hostcfgd/hostcfgd b/files/image_config/hostcfgd/hostcfgd
index 25cfa7c714c4..8c03f2234a94 100755
--- a/files/image_config/hostcfgd/hostcfgd
+++ b/files/image_config/hostcfgd/hostcfgd
@@ -5,6 +5,7 @@ import os
import sys
import subprocess
import syslog
+import copy
import jinja2
from swsssdk import ConfigDBConnector
@@ -155,15 +156,17 @@ class HostConfigDaemon:
def tacacs_server_handler(self, key, data):
self.aaacfg.tacacs_server_update(key, data)
- if data.has_key('passkey'):
- data['passkey'] = obfuscate(data['passkey'])
- syslog.syslog(syslog.LOG_DEBUG, 'value for {} changed to {}'.format(key, data))
+ log_data = copy.deepcopy(data)
+ if log_data.has_key('passkey'):
+ log_data['passkey'] = obfuscate(log_data['passkey'])
+ syslog.syslog(syslog.LOG_DEBUG, 'value of {} changed to {}'.format(key, log_data))
def tacacs_global_handler(self, key, data):
self.aaacfg.tacacs_global_update(key, data)
- if data.has_key('passkey'):
- data['passkey'] = obfuscate(data['passkey'])
- syslog.syslog(syslog.LOG_DEBUG, 'value for {} changed to {}'.format(key, data))
+ log_data = copy.deepcopy(data)
+ if log_data.has_key('passkey'):
+ log_data['passkey'] = obfuscate(log_data['passkey'])
+ syslog.syslog(syslog.LOG_DEBUG, 'value of {} changed to {}'.format(key, log_data))
def start(self):
self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data))
diff --git a/files/image_config/interfaces/interfaces-config.sh b/files/image_config/interfaces/interfaces-config.sh
index 06174790f04a..75660e713e7f 100755
--- a/files/image_config/interfaces/interfaces-config.sh
+++ b/files/image_config/interfaces/interfaces-config.sh
@@ -1,5 +1,7 @@
#!/bin/bash
+ifdown eth0
+
sonic-cfggen -d -t /usr/share/sonic/templates/interfaces.j2 > /etc/network/interfaces
[ -f /var/run/dhclient.eth0.pid ] && kill `cat /var/run/dhclient.eth0.pid` && rm -f /var/run/dhclient.eth0.pid
diff --git a/files/image_config/logrotate/logrotate.d/rsyslog b/files/image_config/logrotate/logrotate.d/rsyslog
index ba550dcd242b..ed54c62082f9 100644
--- a/files/image_config/logrotate/logrotate.d/rsyslog
+++ b/files/image_config/logrotate/logrotate.d/rsyslog
@@ -31,6 +31,7 @@
/var/log/cron.log
/var/log/syslog
/var/log/teamd.log
+/var/log/telemetry.log
/var/log/quagga/bgpd.log
/var/log/quagga/zebra.log
/var/log/swss/sairedis.rec
diff --git a/files/image_config/rsyslog/rsyslog.d/00-sonic.conf b/files/image_config/rsyslog/rsyslog.d/00-sonic.conf
index bc0bbbaf1e61..6e4be4bb6022 100644
--- a/files/image_config/rsyslog/rsyslog.d/00-sonic.conf
+++ b/files/image_config/rsyslog/rsyslog.d/00-sonic.conf
@@ -19,3 +19,9 @@ if $programname contains "teamd_" then {
/var/log/teamd.log
stop
}
+
+## telemetry rules
+if $msg startswith " telemetry" or ($msg startswith " dialout" )then {
+ /var/log/telemetry.log
+ stop
+}
\ No newline at end of file
diff --git a/files/image_config/updategraph/updategraph b/files/image_config/updategraph/updategraph
index 2ce251dfb36e..f0cea0894a9c 100755
--- a/files/image_config/updategraph/updategraph
+++ b/files/image_config/updategraph/updategraph
@@ -66,12 +66,14 @@ if [ -f /tmp/pending_config_migration ]; then
exit 0
fi
-if [ -f /tmp/pending_config_initialization ] && [ "$enabled" != "true" ]; then
- copy_default_minigraph
- reload_minigraph
- sonic-cfggen -d --print-data > /etc/sonic/config_db.json
+if [ -f /tmp/pending_config_initialization ]; then
rm -f /tmp/pending_config_initialization
- exit 0
+ if [ "$enabled" != "true" ]; then
+ copy_default_minigraph
+ reload_minigraph
+ sonic-cfggen -d --print-data > /etc/sonic/config_db.json
+ exit 0
+ fi
fi
if [ "$enabled" = "reload_only" ]; then
diff --git a/files/initramfs-tools/arista-net b/files/initramfs-tools/arista-net
index 1fbe4838adf5..8759746458d6 100644
--- a/files/initramfs-tools/arista-net
+++ b/files/initramfs-tools/arista-net
@@ -26,19 +26,71 @@ for x in "$@"; do
esac
done
+random() {
+ echo $(od -vAn -N1 -tu1 < /dev/urandom)
+}
+
+arista_net_devname() {
+ local pciaddr="$1"
+ local devname_prefix="$2"
+ for path in $(ls -d /sys/class/net/${devname_prefix}* 2>/dev/null); do
+ local devid="$(realpath "$path/device")"
+ if echo "$devid" | grep -q "$pciaddr"; then
+ echo "${path##*/}"
+ return
+ fi
+ done
+}
+
arista_net_rename() {
local device_path="$1"
local new_name="$2"
local from_name="$3"
- for path in $(ls -d /sys/class/net/$from_name* 2>/dev/null); do
- local devid="$(realpath "$path/device")"
- if echo "$devid" | grep -q "$device_path"; then
- local cur_name="${path##*/}"
- ip link set "$cur_name" name "$new_name"
- return
+ devname=$(arista_net_devname "$device_path" "$from_name")
+ [ -n "$devname" ] && ip link set "$devname" name "$new_name"
+}
+
+# Sets the MAC address to the value passed by Aboot through /proc/cmdline
+tg3fixhwaddr()
+{
+ local default_tg3_hwaddr="00:10:18:00:00:00"
+ local pciaddr="$1"
+ local hwaddr="$2"
+
+ devname=$(arista_net_devname "$pciaddr")
+ if [ -z "$devname" ]; then
+ return
+ fi
+
+ driver=$(basename $(readlink "/sys/class/net/$devname/device/driver"))
+ if [ "$driver" != "tg3" ]; then
+ return 0
+ fi
+
+ if [ "$hwaddr" = "$default_tg3_hwaddr" ]; then
+ hwaddr=$(cat /sys/class/net/$devname/address)
+ fi
+
+ if [ "$hwaddr" = "$default_tg3_hwaddr" ]; then
+ hwaddr=$(printf "%02x" "$(($(random) & 0xfe | 0x02))")
+ for i in 1 2 3 4 5; do
+ hwaddr=$(printf "$hwaddr:%02x" "$(($(random) & 0xfe | 0x02))")
+ done
+ fi
+
+ ip link set dev "$devname" addr "$hwaddr"
+}
+
+if [ -n "$aboot_flag" ]; then
+ for item in $items; do
+ key="${item%=*}"
+ value="${item#*=}"
+ hwaddr=$(eval echo \${hwaddr_${key}})
+ if [ -n "$hwaddr" ]; then
+ tg3fixhwaddr "$value" "$hwaddr"
fi
done
-}
+fi
# Iterate over all the net_maX items found in the cmdline two times.
# First time renaming the interfaces to maX.
diff --git a/installer/x86_64/install.sh b/installer/x86_64/install.sh
index 0e4321345167..949c052acb89 100755
--- a/installer/x86_64/install.sh
+++ b/installer/x86_64/install.sh
@@ -446,7 +446,11 @@ fi
# Decompress the file for the file system directly to the partition
unzip -o $ONIE_INSTALLER_PAYLOAD -x "$FILESYSTEM_DOCKERFS" -d $demo_mnt/$image_dir
-TAR_EXTRA_OPTION="--numeric-owner"
+if [ "$install_env" = "onie" ]; then
+ TAR_EXTRA_OPTION="--numeric-owner"
+else
+ TAR_EXTRA_OPTION="--numeric-owner --warning=no-timestamp"
+fi
mkdir -p $demo_mnt/$image_dir/$DOCKERFS_DIR
unzip -op $ONIE_INSTALLER_PAYLOAD "$FILESYSTEM_DOCKERFS" | tar xz $TAR_EXTRA_OPTION -f - -C $demo_mnt/$image_dir/$DOCKERFS_DIR
@@ -455,7 +459,8 @@ if [ "$install_env" = "onie" ]; then
if [ -f /etc/machine-build.conf ]; then
# onie_ variable are generate at runtime.
# they are no longer hardcoded in /etc/machine.conf
- set | grep ^onie_ > $demo_mnt/machine.conf
+ # also remove single quotes around the value
+ set | grep ^onie | sed -e "s/='/=/" -e "s/'$//" > $demo_mnt/machine.conf
else
cp /etc/machine.conf $demo_mnt
fi
diff --git a/platform/broadcom/sonic-platform-modules-arista b/platform/broadcom/sonic-platform-modules-arista
index 3e8345b5d2ec..6fe9de4dd52b 160000
--- a/platform/broadcom/sonic-platform-modules-arista
+++ b/platform/broadcom/sonic-platform-modules-arista
@@ -1 +1 @@
-Subproject commit 3e8345b5d2ec2a2127c201c7749b9283b8daa618
+Subproject commit 6fe9de4dd52bba4c5856567a8f5624e75e9af66d
diff --git a/platform/mellanox/fw.mk b/platform/mellanox/fw.mk
index ce3c55c59c09..0ac9dd9b7aa6 100644
--- a/platform/mellanox/fw.mk
+++ b/platform/mellanox/fw.mk
@@ -1,6 +1,6 @@
# mellanox firmware
-MLNX_FW_VERSION = 13.1620.0192
+MLNX_FW_VERSION = 13.1620.0208
MLNX_FW_FILE = fw-SPC-rel-$(subst .,_,$(MLNX_FW_VERSION))-EVB.mfa
$(MLNX_FW_FILE)_URL = $(MLNX_SDK_BASE_URL)/$(MLNX_FW_FILE)
SONIC_ONLINE_FILES += $(MLNX_FW_FILE)
diff --git a/platform/mellanox/mlnx-sai.mk b/platform/mellanox/mlnx-sai.mk
index 666e90e2b20f..23ef8c60458b 100644
--- a/platform/mellanox/mlnx-sai.mk
+++ b/platform/mellanox/mlnx-sai.mk
@@ -1,7 +1,7 @@
# Mellanox SAI
-MLNX_SAI_VERSION = SAIRel1.11.2-master
-MLNX_SAI_REVISION = f0651fc85d88d03001b72a03a4d15e269e198b38
+MLNX_SAI_VERSION = SAIRel1.11.4-master
+MLNX_SAI_REVISION = 1a44c29b22e1f36f4856f4aee92ad513c963c2b8
export MLNX_SAI_VERSION MLNX_SAI_REVISION
diff --git a/platform/mellanox/sdk.mk b/platform/mellanox/sdk.mk
index 9c440c0a2fb8..2ebb7d23f9c6 100644
--- a/platform/mellanox/sdk.mk
+++ b/platform/mellanox/sdk.mk
@@ -1,5 +1,5 @@
-MLNX_SDK_BASE_URL = https://github.com/Mellanox/SAI-Implementation/raw/fb4cd4cec4b8718c54d5bf5c64df9b474738f404/sdk
-MLNX_SDK_VERSION = 4.2.7101
+MLNX_SDK_BASE_URL = https://github.com/Mellanox/SAI-Implementation/raw/6367854b48b73470a6e093f6fbbd45b3341edaba/sdk
+MLNX_SDK_VERSION = 4.2.7201
MLNX_SDK_RDEBS += $(APPLIBS) $(IPROUTE2_MLNX) $(SX_ACL_RM) $(SX_COMPLIB) \
$(SX_EXAMPLES) $(SX_GEN_UTILS) $(SX_SCEW) $(SX_SDN_HAL) \
$(SXD_LIBS) $(TESTX)
diff --git a/rules/config b/rules/config
index 49eb8d57e984..86d106637de2 100644
--- a/rules/config
+++ b/rules/config
@@ -27,12 +27,12 @@ DEFAULT_USERNAME = admin
DEFAULT_PASSWORD = YourPaSsWoRd
# ENABLE_DHCP_GRAPH_SERVICE - specify the source of minigraph to generate configuration file.
-# If set to y SONiC will get the minigraph from graph service. Graph service URL need to be
+# If set to y SONiC will get the minigraph from graph service. Graph service URL need to be
# passed through DHCP option 225.
# If not set (default behavior) the default minigraph built into the image will be used.
# ENABLE_DHCP_GRAPH_SERVICE = y
-# SHUTDOWN_BGP_ON_START - if set to y all bgp sessions will be in admin down state when
+# SHUTDOWN_BGP_ON_START - if set to y all bgp sessions will be in admin down state when
# bgp service starts.
# SHUTDOWN_BGP_ON_START = y
@@ -52,6 +52,9 @@ SONIC_ROUTING_STACK = quagga
# ENABLE_SYNCD_RPC - build docker-syncd with rpc packages for testing purposes.
# Uncomment to enable:
# ENABLE_SYNCD_RPC = y
-
+
# Enable Origanization Extensions - Specific to the deployment scenarios of the Organization
ENABLE_ORGANIZATION_EXTENSIONS = y
+
+# ENABLE_SYSTEM_TELEMETRY - build docker-sonic-telemetry for system telemetry support
+# ENABLE_SYSTEM_TELEMETRY = y
diff --git a/rules/docker-telemetry.mk b/rules/docker-telemetry.mk
new file mode 100644
index 000000000000..fca3b8a39a70
--- /dev/null
+++ b/rules/docker-telemetry.mk
@@ -0,0 +1,15 @@
+# docker image for telemetry agent
+
+DOCKER_TELEMETRY = docker-sonic-telemetry.gz
+$(DOCKER_TELEMETRY)_PATH = $(DOCKERS_PATH)/docker-sonic-telemetry
+$(DOCKER_TELEMETRY)_DEPENDS += $(REDIS_TOOLS) $(SONIC_TELEMETRY)
+$(DOCKER_TELEMETRY)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE)
+SONIC_DOCKER_IMAGES += $(DOCKER_TELEMETRY)
+ifeq ($(ENABLE_SYSTEM_TELEMETRY), y)
+SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_TELEMETRY)
+endif
+
+$(DOCKER_TELEMETRY)_CONTAINER_NAME = telemetry
+$(DOCKER_TELEMETRY)_RUN_OPT += --net=host --privileged -t
+$(DOCKER_TELEMETRY)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro
+
diff --git a/rules/telemetry.mk b/rules/telemetry.mk
new file mode 100644
index 000000000000..a160bf50899c
--- /dev/null
+++ b/rules/telemetry.mk
@@ -0,0 +1,5 @@
+# SONiC telemetry package
+
+SONIC_TELEMETRY = sonic-telemetry_0.1_amd64.deb
+$(SONIC_TELEMETRY)_SRC_PATH = $(SRC_PATH)/telemetry
+SONIC_DPKG_DEBS += $(SONIC_TELEMETRY)
diff --git a/slave.mk b/slave.mk
index 7e842a7a608e..7430f3a80d10 100644
--- a/slave.mk
+++ b/slave.mk
@@ -12,8 +12,8 @@ GUID = $(shell id -g)
.SECONDEXPANSION:
-SPACE :=
-SPACE +=
+SPACE :=
+SPACE +=
###############################################################################
## General definitions
@@ -107,6 +107,7 @@ $(info "ENABLE_SYNCD_RPC" : "$(ENABLE_SYNCD_RPC)")
$(info "ENABLE_ORGANIZATION_EXTENSIONS" : "$(ENABLE_ORGANIZATION_EXTENSIONS)")
$(info "HTTP_PROXY" : "$(HTTP_PROXY)")
$(info "HTTPS_PROXY" : "$(HTTPS_PROXY)")
+$(info "ENABLE_SYSTEM_TELEMETRY" : "$(ENABLE_SYSTEM_TELEMETRY)")
$(info )
###############################################################################
@@ -441,7 +442,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
export image_type="$($*_IMAGE_TYPE)"
export sonicadmin_user="$(USERNAME)"
export sonic_asic_platform="$(CONFIGURED_PLATFORM)"
- export enable_organization_extensions="$(ENABLE_ORGANIZATION_EXTENSIONS)"
+ export enable_organization_extensions="$(ENABLE_ORGANIZATION_EXTENSIONS)"
export enable_dhcp_graph_service="$(ENABLE_DHCP_GRAPH_SERVICE)"
export shutdown_bgp_on_start="$(SHUTDOWN_BGP_ON_START)"
export enable_pfcwd_on_start="$(ENABLE_PFCWD_ON_START)"
@@ -451,7 +452,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
export config_engine_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CONFIG_ENGINE))"
export swsssdk_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SWSSSDK_PY2))"
export platform_common_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY2))"
-
+
$(foreach docker, $($*_DOCKERS),\
export docker_image="$(docker)"
export docker_image_name="$(basename $(docker))"
@@ -472,7 +473,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
j2 -f env files/initramfs-tools/union-mount.j2 onie-image.conf > files/initramfs-tools/union-mount
j2 -f env files/initramfs-tools/arista-convertfs.j2 onie-image.conf > files/initramfs-tools/arista-convertfs
- $(if $($*_DOCKERS),
+ $(if $($*_DOCKERS),
j2 files/build_templates/sonic_debian_extension.j2 > sonic_debian_extension.sh
chmod +x sonic_debian_extension.sh,
)
diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py
index 34fcf1bcee25..f989129a439e 100644
--- a/src/sonic-config-engine/minigraph.py
+++ b/src/sonic-config-engine/minigraph.py
@@ -286,6 +286,7 @@ def parse_meta(meta, hname):
syslog_servers = []
dhcp_servers = []
ntp_servers = []
+ tacacs_servers = []
mgmt_routes = []
erspan_dst = []
deployment_id = None
@@ -296,20 +297,22 @@ def parse_meta(meta, hname):
for device_property in properties.findall(str(QName(ns1, "DeviceProperty"))):
name = device_property.find(str(QName(ns1, "Name"))).text
value = device_property.find(str(QName(ns1, "Value"))).text
- value_group = value.split(';') if value and value != "" else []
+ value_group = value.strip().split(';') if value and value != "" else []
if name == "DhcpResources":
dhcp_servers = value_group
elif name == "NtpResources":
ntp_servers = value_group
elif name == "SyslogResources":
syslog_servers = value_group
+ elif name == "TacacsServer":
+ tacacs_servers = value_group
elif name == "ForcedMgmtRoutes":
mgmt_routes = value_group
elif name == "ErspanDestinationIpv4":
erspan_dst = value_group
elif name == "DeploymentId":
deployment_id = value
- return syslog_servers, dhcp_servers, ntp_servers, mgmt_routes, erspan_dst, deployment_id
+ return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id
def parse_deviceinfo(meta, hwsku):
port_speeds = {}
@@ -352,6 +355,7 @@ def parse_xml(filename, platform=None, port_config_file=None):
syslog_servers = []
dhcp_servers = []
ntp_servers = []
+ tacacs_servers = []
mgmt_routes = []
erspan_dst = []
bgp_peers_with_range = None
@@ -377,7 +381,7 @@ def parse_xml(filename, platform=None, port_config_file=None):
elif child.tag == str(QName(ns, "UngDec")):
(u_neighbors, u_devices, _, _, _, _) = parse_png(child, hostname)
elif child.tag == str(QName(ns, "MetadataDeclaration")):
- (syslog_servers, dhcp_servers, ntp_servers, mgmt_routes, erspan_dst, deployment_id) = parse_meta(child, hostname)
+ (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id) = parse_meta(child, hostname)
elif child.tag == str(QName(ns, "DeviceInfos")):
(port_speeds, port_descriptions) = parse_deviceinfo(child, hwsku)
@@ -433,6 +437,7 @@ def parse_xml(filename, platform=None, port_config_file=None):
results['SYSLOG_SERVER'] = dict((item, {}) for item in syslog_servers)
results['DHCP_SERVER'] = dict((item, {}) for item in dhcp_servers)
results['NTP_SERVER'] = dict((item, {}) for item in ntp_servers)
+ results['TACPLUS_SERVER'] = dict((item, {'priority': '1', 'tcp_port': '49'}) for item in tacacs_servers)
results['ACL_TABLE'] = acls
mirror_sessions = {}
diff --git a/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml b/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml
new file mode 100644
index 000000000000..28044f1c8780
--- /dev/null
+++ b/src/sonic-config-engine/tests/simple-sample-graph-metadata.xml
@@ -0,0 +1,317 @@
+
+
+
+
+
+ false
+ switch-t0
+ 10.0.0.56
+ ARISTA01T1
+ 10.0.0.57
+ 1
+ 180
+ 60
+
+
+ switch-t0
+ FC00::71
+ ARISTA01T1
+ FC00::72
+ 1
+ 180
+ 60
+
+
+ false
+ switch-t0
+ 10.0.0.58
+ ARISTA02T1
+ 10.0.0.59
+ 1
+ 180
+ 60
+
+
+ switch-t0
+ FC00::75
+ ARISTA02T1
+ FC00::76
+ 1
+ 180
+ 60
+
+
+
+
+ 65100
+ switch-t0
+
+
+ 10.0.0.57
+
+
+
+
+
+ 10.0.0.59
+
+
+
+
+
+
+
+
+ 64600
+ ARISTA01T1
+
+
+
+ 64600
+ ARISTA02T1
+
+
+
+ 64600
+ ARISTA03T1
+
+
+
+ 64600
+ ARISTA04T1
+
+
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 10.1.0.32/32
+
+ 10.1.0.32/32
+
+
+ HostIP1
+ Loopback0
+
+ FC00:1::32/128
+
+ FC00:1::32/128
+
+
+
+
+ HostIP
+ eth0
+
+ 10.0.0.100/24
+
+ 10.0.0.100/24
+
+
+
+
+
+
+ switch-t0
+
+
+ PortChannel01
+ fortyGigE0/4
+
+
+
+
+
+ ab1
+ fortyGigE0/8
+ 192.0.0.1;192.0.0.2
+ 1000
+ 1000
+ 192.168.0.0/27
+
+
+
+
+
+ PortChannel01
+ 10.0.0.56/31
+
+
+
+ PortChannel01
+ FC00::71/126
+
+
+
+ fortyGigE0/0
+ 10.0.0.58/31
+
+
+
+ fortyGigE0/0
+ FC00::75/126
+
+
+
+ ab1
+ 192.168.0.1/27
+
+
+
+
+
+ PortChannel01
+ DataAcl
+ DataPlane
+
+
+ SNMP
+ SNMP_ACL
+ SNMP
+
+
+
+
+
+
+
+
+
+
+ switch-t0
+ Force10-S6000
+
+
+ ARISTA01T1
+ Arista
+
+
+ ARISTA02T1
+ Arista
+
+
+ ARISTA03T1
+ Arista
+
+
+ ARISTA04T1
+ Arista
+
+
+
+
+
+
+ switch-t0
+
+
+ DeploymentId
+
+ 1
+
+
+ ErspanDestinationIpv4
+
+ 10.0.100.1
+
+
+ NtpResources
+
+ 10.0.10.1;10.0.10.2
+
+
+
+ SnmpResources
+
+ 10.0.10.3;10.0.10.4
+
+
+
+ SyslogResources
+
+ 10.0.10.5;10.0.10.6;
+
+
+
+ TacacsServer
+
+ 10.0.10.7;10.0.10.8
+
+
+
+
+
+
+
+
+ true
+
+
+ DeviceInterface
+
+ true
+ true
+ 1
+ fortyGigE0/0
+
+ false
+ 0
+ 0
+ 10000
+
+
+ DeviceInterface
+
+ true
+ true
+ 1
+ fortyGigE0/4
+
+ false
+ 0
+ 0
+ 25000
+
+
+ DeviceInterface
+
+ true
+ true
+ 1
+ fortyGigE0/8
+
+ false
+ 0
+ 0
+ 40000
+ Interface description
+
+
+ DeviceInterface
+
+ true
+ true
+ 1
+ fortyGigE0/12
+
+ false
+ 0
+ 0
+ 100000
+ Interface description
+
+
+ true
+ 0
+ Force10-S6000
+
+
+ switch-t0
+ Force10-S6000
+
diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py
index 3ee689622577..d187cfd26b8b 100644
--- a/src/sonic-config-engine/tests/test_cfggen.py
+++ b/src/sonic-config-engine/tests/test_cfggen.py
@@ -10,6 +10,7 @@ def setUp(self):
self.sample_graph = os.path.join(self.test_dir, 'sample_graph.xml')
self.sample_graph_t0 = os.path.join(self.test_dir, 't0-sample-graph.xml')
self.sample_graph_simple = os.path.join(self.test_dir, 'simple-sample-graph.xml')
+ self.sample_graph_metadata = os.path.join(self.test_dir, 'simple-sample-graph-metadata.xml')
self.sample_graph_pc_test = os.path.join(self.test_dir, 'pc-test-graph.xml')
self.sample_graph_bgp_speaker = os.path.join(self.test_dir, 't0-sample-bgp-speaker.xml')
self.sample_device_desc = os.path.join(self.test_dir, 'device.xml')
@@ -143,3 +144,19 @@ def test_minigraph_ethernet_interfaces(self):
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet12\']"'
output = self.run_script(argument)
self.assertEqual(output.strip(), "{'alias': 'fortyGigE0/12', 'lanes': '33,34,35,36', 'fec': 'rs', 'speed': '100000', 'description': 'Interface description'}")
+
+ def test_metadata_everflow(self):
+ argument = '-m "' + self.sample_graph_metadata + '" -p "' + self.port_config + '" -v "MIRROR_SESSION"'
+ output = self.run_script(argument)
+ self.assertEqual(output.strip(), "{'everflow0': {'src_ip': '10.1.0.32', 'dst_ip': '10.0.100.1'}}")
+
+ def test_metadata_tacacs(self):
+ argument = '-m "' + self.sample_graph_metadata + '" -p "' + self.port_config + '" -v "TACPLUS_SERVER"'
+ output = self.run_script(argument)
+ self.assertEqual(output.strip(), "{'10.0.10.7': {'priority': '1', 'tcp_port': '49'}, '10.0.10.8': {'priority': '1', 'tcp_port': '49'}}")
+
+ def test_metadata_ntp(self):
+ argument = '-m "' + self.sample_graph_metadata + '" -p "' + self.port_config + '" -v "NTP_SERVER"'
+ output = self.run_script(argument)
+ self.assertEqual(output.strip(), "{'10.0.10.1': {}, '10.0.10.2': {}}")
+
diff --git a/src/sonic-platform-common b/src/sonic-platform-common
index 0581611b7be5..560b465cb516 160000
--- a/src/sonic-platform-common
+++ b/src/sonic-platform-common
@@ -1 +1 @@
-Subproject commit 0581611b7be5cc52aea2877199785fe72f759a58
+Subproject commit 560b465cb5166d0ad0c56312292bba990a122419
diff --git a/src/sonic-sairedis b/src/sonic-sairedis
index d35642238905..c860472a3d8c 160000
--- a/src/sonic-sairedis
+++ b/src/sonic-sairedis
@@ -1 +1 @@
-Subproject commit d35642238905ae4e9a0d259797b578eddd5a7156
+Subproject commit c860472a3d8c16cad8a44fd7f76e848c39651f2e
diff --git a/src/sonic-swss b/src/sonic-swss
index ce78bf568500..d711d2cf5783 160000
--- a/src/sonic-swss
+++ b/src/sonic-swss
@@ -1 +1 @@
-Subproject commit ce78bf568500397dac5b2f2cd1a9779cfc50ff62
+Subproject commit d711d2cf57839589aa7d6653b252305c31f8c2b0
diff --git a/src/sonic-utilities b/src/sonic-utilities
index bf8d2b430e9d..3f2d7bb4beaf 160000
--- a/src/sonic-utilities
+++ b/src/sonic-utilities
@@ -1 +1 @@
-Subproject commit bf8d2b430e9dfea4fc9f9626acb2663aa527da91
+Subproject commit 3f2d7bb4beaf3987db0c3e6fb57ae7ba51390a16
diff --git a/src/telemetry/Makefile b/src/telemetry/Makefile
new file mode 100644
index 000000000000..91a822d4f93c
--- /dev/null
+++ b/src/telemetry/Makefile
@@ -0,0 +1,20 @@
+export GOPATH=/tmp/go
+
+INSTALL := /usr/bin/install
+
+all: sonic-telemetry
+
+sonic-telemetry:
+ /usr/local/go/bin/go get -v github.com/Azure/sonic-telemetry/telemetry
+ /usr/local/go/bin/go get -v github.com/Azure/sonic-telemetry/dialout/dialout_client_cli
+
+install:
+ $(INSTALL) -D ${GOPATH}/bin/telemetry $(DESTDIR)/usr/sbin/telemetry
+ $(INSTALL) -D ${GOPATH}/bin/dialout_client_cli $(DESTDIR)/usr/sbin/dialout_client_cli
+
+deinstall:
+ rm $(DESTDIR)/usr/sbin/telemetry
+ rm $(DESTDIR)/usr/sbin/dialout_client_cli
+
+clean:
+ rm -fr ${GOPATH}
diff --git a/src/telemetry/debian/changelog b/src/telemetry/debian/changelog
new file mode 100644
index 000000000000..77dab629040e
--- /dev/null
+++ b/src/telemetry/debian/changelog
@@ -0,0 +1,5 @@
+sonic-telemetry (0.1) UNRELEASED; urgency=medium
+
+ * Initial release.
+
+ -- Jipan Yang Sat, 24 Mar 2018 12:48:22 -0700
diff --git a/src/telemetry/debian/compat b/src/telemetry/debian/compat
new file mode 100644
index 000000000000..ec635144f600
--- /dev/null
+++ b/src/telemetry/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/src/telemetry/debian/control b/src/telemetry/debian/control
new file mode 100644
index 000000000000..f1b6a7c07282
--- /dev/null
+++ b/src/telemetry/debian/control
@@ -0,0 +1,17 @@
+Source: sonic-telemetry
+Section: devel
+Priority: optional
+Maintainer: Jipan Yang
+Build-Depends: debhelper (>= 8.0.0),
+ dh-systemd
+Standards-Version: 3.9.3
+Homepage: https://github.com/Azure/sonic-telemetry
+XS-Go-Import-Path: github.com/Azure/sonic-telemetry
+
+Package: sonic-telemetry
+Architecture: any
+Built-Using: ${misc:Built-Using}
+Depends: ${misc:Depends},
+ ${shlibs:Depends}
+Description: SONiC telemetry
+ sonic-telemetry
\ No newline at end of file
diff --git a/src/telemetry/debian/rules b/src/telemetry/debian/rules
new file mode 100644
index 000000000000..3995a26d7fcd
--- /dev/null
+++ b/src/telemetry/debian/rules
@@ -0,0 +1,3 @@
+#!/usr/bin/make -f
+%:
+ dh $@ --with systemd
diff --git a/src/telemetry/debian/telemetry.init.d b/src/telemetry/debian/telemetry.init.d
new file mode 100644
index 000000000000..2fea32e17c49
--- /dev/null
+++ b/src/telemetry/debian/telemetry.init.d
@@ -0,0 +1,14 @@
+#!/bin/bash
+#
+### BEGIN INIT INFO
+# Provides: sonic-telemetry
+# Required-Start: $local_fs $network $remote_fs $syslog
+# Required-Stop: $local_fs $network $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: start and stop the telemetry
+# Description: sonic-telemetry is an implementation of sonic telemetry daemon in Go
+### END INIT INFO
+#
+
+exit 0