Merge remote-tracking branch 'azure/master' into bf-master

This commit is contained in:
kram 2017-12-13 17:49:24 -08:00
commit e2696683ff
27 changed files with 1279 additions and 623 deletions

23
.gitignore vendored
View File

@ -12,28 +12,31 @@ target/
# Subdirectories in src
src/hiredis/*
!src/hiredis/Makefile
src/igb/*
!src/igb/Makefile
src/initramfs-tools/*
!src/initramfs-tools/Makefile
src/redis/*
!src/redis/Makefile
src/isc-dhcp/*
!src/isc-dhcp/Makefile
!src/isc-dhcp/patch/
src/libnl3/*
!src/libnl3/Makefile
src/libteam/*
!src/libteam/Makefile
src/snmpd/*
!src/snmpd/Makefile
src/thrift/*
!src/thrift/Makefile
src/sonic-device-data/src/device/
src/sonic-device-data/src/debian/
src/igb/*
!src/igb/Makefile
src/mpdecimal/*
!src/mpdecimal/Makefile
src/python3/*
!src/python3/Makefile
src/redis/*
!src/redis/Makefile
src/snmpd/*
!src/snmpd/Makefile
src/sonic-device-data/src/device/
src/sonic-device-data/src/debian/
src/supervisor/*
!src/supervisor/Makefile
src/thrift/*
!src/thrift/Makefile
# Autogenerated Dockerfiles
dockers/docker-base/Dockerfile

View File

@ -1,80 +1,79 @@
#
# psuutil.py
# Platform-specific PSU status interface for SONiC
#
import os.path
try:
from sonic_psu.psu_base import PsuBase
except ImportError, e:
raise ImportError(str(e) + "- required module not found")
class PsuUtil(PsuBase):
"""Platform-specific PSUutil class"""
def __init__(self):
PsuBase.__init__(self)
# Get a mailbox register
def get_pmc_register(self, reg_name):
mailbox_dir = "/sys/devices/platform/dell_s6100_lpc"
retval = 'ERR'
mb_reg_file = mailbox_dir+'/' + reg_name
if (not os.path.isfile(mb_reg_file)):
print mb_reg_file, 'not found !'
return retval
try:
with open(mb_reg_file, 'r') as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open ", mb_reg_file, "file !")
retval = retval.rstrip('\r\n')
return retval
def get_num_psus(self):
"""
Retrieves the number of PSUs available on the device
:return: An integer, the number of PSUs available on the device
"""
S6100_MAX_PSUS = 2
return S6100_MAX_PSUS
def get_psu_status(self, index):
"""
Retrieves the oprational status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is operating properly, False if PSU is\
faulty
"""
status = 0
psu_status = self.get_pmc_register('psu_'+str(index)+'_status')
if (psu_status != 'ERR'):
psu_status = int(psu_status, 16)
# Check for PSU statuse
if (~psu_status & 0b1000) or (psu_status & 0b0100):
status = 1
return status
def get_psu_presence(self, index):
"""
Retrieves the presence status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is plugged, False if not
"""
status = 0
psu_presence = self.get_pmc_register('psu_'+str(index)+'_status')
if (psu_presence != 'ERR'):
psu_presence = int(psu_presence, 16)
# Check for PSU presence
if (~psu_presence & 0b1):
status = 1
return status
#
# psuutil.py
# Platform-specific PSU status interface for SONiC
#
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)
# Get a mailbox register
def get_pmc_register(self, reg_name):
mailbox_dir = "/sys/devices/platform/dell_s6100_lpc"
retval = 'ERR'
mb_reg_file = mailbox_dir+'/' + reg_name
if (not os.path.isfile(mb_reg_file)):
return retval
try:
with open(mb_reg_file, 'r') as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open ", mb_reg_file, "file !")
retval = retval.rstrip('\r\n')
return retval
def get_num_psus(self):
"""
Retrieves the number of PSUs available on the device
:return: An integer, the number of PSUs available on the device
"""
S6100_MAX_PSUS = 2
return S6100_MAX_PSUS
def get_psu_status(self, index):
"""
Retrieves the oprational status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is operating properly, False if PSU is\
faulty
"""
status = 0
psu_status = self.get_pmc_register('psu_'+str(index)+'_status')
if (psu_status != 'ERR'):
psu_status = int(psu_status, 16)
# Check for PSU statuse
if (~psu_status & 0b1000) or (psu_status & 0b0100):
status = 1
return status
def get_psu_presence(self, index):
"""
Retrieves the presence status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is plugged, False if not
"""
status = 0
psu_presence = self.get_pmc_register('psu_'+str(index)+'_status')
if (psu_presence != 'ERR'):
psu_presence = int(psu_presence, 16)
# Check for PSU presence
if (~psu_presence & 0b1):
status = 1
return status

View File

@ -8,7 +8,7 @@ import os.path
try:
from sonic_psu.psu_base import PsuBase
except ImportError, e:
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@ -24,7 +24,6 @@ class PsuUtil(PsuBase):
retval = 'ERR'
mb_reg_file = mailbox_dir+'/' + reg_name
if (not os.path.isfile(mb_reg_file)):
print mb_reg_file, 'not found !'
return retval
try:

View File

@ -128,6 +128,12 @@ sudo cp $IMAGE_CONFIGS/interfaces/*.j2 $FILESYSTEM_ROOT/usr/share/sonic/template
# Copy initial interfaces configuration file, will be overwritten on first boot
sudo cp $IMAGE_CONFIGS/interfaces/init_interfaces $FILESYSTEM_ROOT/etc/network
# Copy hostcfgd files
sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd.service $FILESYSTEM_ROOT/etc/systemd/system/
sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable hostcfgd.service
sudo cp $IMAGE_CONFIGS/hostcfgd/hostcfgd $FILESYSTEM_ROOT/usr/bin/
sudo cp $IMAGE_CONFIGS/hostcfgd/*.j2 $FILESYSTEM_ROOT/usr/share/sonic/templates/
# Copy hostname configuration scripts
sudo cp $IMAGE_CONFIGS/hostname/hostname-config.service $FILESYSTEM_ROOT/etc/systemd/system/
sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable hostname-config.service

View File

@ -0,0 +1,43 @@
# THIS IS AN AUTO-GENERATED FILE
#
# /etc/pam.d/common-auth- authentication settings common to all services
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the
# traditional Unix authentication mechanisms.
#
# here are the per-package modules (the "Primary" block)
{% if auth['login'] == 'local' %}
auth [success=1 default=ignore] pam_unix.so nullok try_first_pass
{% elif auth['login'] == 'local,tacacs+' %}
auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_unix.so nullok try_first_pass
{% for server in servers | sub(0, -1) %}
auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_tacplus.so server={{ server.ip }}:{{ server.tcp_port }} secret={{ server.passkey }} login={{ server.auth_type }} timeout={{ server.timeout }} try_first_pass
{% endfor %}
{% if servers | count %}
{% set last_server = servers | last %}
auth [success=1 default=ignore] pam_tacplus.so server={{ last_server.ip }}:{{ last_server.tcp_port }} secret={{ last_server.passkey }} login={{ last_server.auth_type }} timeout={{ last_server.timeout }} try_first_pass
{% endif %}
{% elif auth['login'] == 'tacacs+' or auth['login'] == 'tacacs+,local' %}
{% for server in servers %}
auth [success=done new_authtok_reqd=done default=ignore{{ ' auth_err=die' if not auth['failthrough'] }}] pam_tacplus.so server={{ server.ip }}:{{ server.tcp_port }} secret={{ server.passkey }} login={{ server.auth_type }} timeout={{ server.timeout }} try_first_pass
{% endfor %}
auth [success=1 default=ignore] pam_unix.so nullok try_first_pass
{% else %}
auth [success=1 default=ignore] pam_unix.so nullok try_first_pass
{% endif %}
#
# here's the fallback if no module succeeds
auth requisite pam_deny.so
# prime the stack with a positive return value if there isn't one already;
# this avoids us returning an error just because nothing sets a success code
# since the modules above will each just jump around
auth required pam_permit.so
# and here are more per-package modules (the "Additional" block)

View File

@ -0,0 +1,172 @@
#!/usr/bin/python -u
# -*- coding: utf-8 -*-
import os
import sys
import subprocess
import syslog
import jinja2
from swsssdk import ConfigDBConnector
# FILE
PAM_AUTH_CONF = "/etc/pam.d/common-auth-sonic"
PAM_AUTH_CONF_TEMPLATE = "/usr/share/sonic/templates/common-auth-sonic.j2"
NSS_TACPLUS_CONF = "/etc/tacplus_nss.conf"
NSS_TACPLUS_CONF_TEMPLATE = "/usr/share/sonic/templates/tacplus_nss.conf.j2"
NSS_CONF = "/etc/nsswitch.conf"
# TACACS+
TACPLUS_SERVER_PASSKEY_DEFAULT = ""
TACPLUS_SERVER_TIMEOUT_DEFAULT = "5"
TACPLUS_SERVER_AUTH_TYPE_DEFAULT = "pap"
def is_true(val):
if val == 'True' or val == 'true':
return True
else:
return False
def sub(l, start, end):
return l[start:end]
class AaaCfg(object):
def __init__(self):
self.auth_default = {
'login': 'local',
'failthrough': True,
'fallback': True
}
self.tacplus_global_default = {
'auth_type': TACPLUS_SERVER_AUTH_TYPE_DEFAULT,
'timeout': TACPLUS_SERVER_TIMEOUT_DEFAULT,
'passkey': TACPLUS_SERVER_PASSKEY_DEFAULT
}
self.auth = {}
self.tacplus_global = {}
self.tacplus_servers = {}
self.debug = False
# Load conf from ConfigDb
def load(self, aaa_conf, tac_global_conf, tacplus_conf):
for row in aaa_conf:
self.aaa_update(row, aaa_conf[row], modify_conf=False)
for row in tac_global_conf:
self.tacacs_global_update(row, tac_global_conf[row], modify_conf=False)
for row in tacplus_conf:
self.tacacs_server_update(row, tacplus_conf[row], modify_conf=False)
self.modify_conf_file()
def aaa_update(self, key, data, modify_conf=True):
if key == 'authentication':
self.auth = data
if 'failthrough' in data:
self.auth['failthrough'] = is_true(data['failthrough'])
if 'debug' in data:
self.debug = is_true(data['debug'])
if modify_conf:
self.modify_conf_file()
def tacacs_global_update(self, key, data, modify_conf=True):
if key == 'global':
self.tacplus_global = data
if modify_conf:
self.modify_conf_file()
def tacacs_server_update(self, key, data, modify_conf=True):
if data == {}:
if key in self.tacplus_servers:
del self.tacplus_servers[key]
else:
self.tacplus_servers[key] = data
if modify_conf:
self.modify_conf_file()
def modify_conf_file(self):
auth = self.auth_default.copy()
auth.update(self.auth)
tacplus_global = self.tacplus_global_default.copy()
tacplus_global.update(self.tacplus_global)
servers_conf = []
if self.tacplus_servers:
for addr in self.tacplus_servers:
server = tacplus_global.copy()
server['ip'] = addr
server.update(self.tacplus_servers[addr])
servers_conf.append(server)
sorted(servers_conf, key=lambda t: t['priority'], reverse=True)
template_file = os.path.abspath(PAM_AUTH_CONF_TEMPLATE)
env = jinja2.Environment(loader=jinja2.FileSystemLoader('/'), trim_blocks=True)
env.filters['sub'] = sub
template = env.get_template(template_file)
pam_conf = template.render(auth=auth, servers=servers_conf)
with open(PAM_AUTH_CONF, 'w') as f:
f.write(pam_conf)
# Modify common-auth include file in /etc/pam.d/login and sshd
if os.path.isfile(PAM_AUTH_CONF):
os.system("sed -i -e '/^@include/s/common-auth$/common-auth-sonic/' /etc/pam.d/sshd")
os.system("sed -i -e '/^@include/s/common-auth$/common-auth-sonic/' /etc/pam.d/login")
else:
os.system("sed -i -e '/^@include/s/common-auth-sonic$/common-auth/' /etc/pam.d/sshd")
os.system("sed -i -e '/^@include/s/common-auth-sonic$/common-auth/' /etc/pam.d/login")
# Add tacplus in nsswitch.conf if TACACS+ enable
if 'tacacs+' in auth['login']:
if os.path.isfile(NSS_CONF):
os.system("sed -i -e '/tacplus/b' -e '/^passwd/s/compat/& tacplus/' /etc/nsswitch.conf")
else:
if os.path.isfile(NSS_CONF):
os.system("sed -i -e '/^passwd/s/ tacplus//' /etc/nsswitch.conf")
# Set tacacs+ server in nss-tacplus conf
template_file = os.path.abspath(NSS_TACPLUS_CONF_TEMPLATE)
template = env.get_template(template_file)
nss_tacplus_conf = template.render(debug=self.debug, servers=servers_conf)
with open(NSS_TACPLUS_CONF, 'w') as f:
f.write(nss_tacplus_conf)
class HostConfigDaemon:
def __init__(self):
self.config_db = ConfigDBConnector()
self.config_db.connect(wait_for_init=True, retry_on=True)
syslog.syslog(syslog.LOG_INFO, 'ConfigDB connect success')
aaa = self.config_db.get_table('AAA')
tacacs_global = self.config_db.get_table('TACPLUS')
tacacs_server = self.config_db.get_table('TACPLUS_SERVER')
self.aaacfg = AaaCfg()
self.aaacfg.load(aaa, tacacs_global, tacacs_server)
def aaa_handler(self, key, data):
syslog.syslog(syslog.LOG_DEBUG, 'value for {} changed to {}'.format(key, data))
self.aaacfg.aaa_update(key, data)
def tacacs_server_handler(self, key, data):
syslog.syslog(syslog.LOG_DEBUG, 'value for {} changed to {}'.format(key, data))
self.aaacfg.tacacs_server_update(key, data)
def tacacs_global_handler(self, key, data):
syslog.syslog(syslog.LOG_DEBUG, 'value for {} changed to {}'.format(key, data))
self.aaacfg.tacacs_global_update(key, data)
def start(self):
self.config_db.subscribe('AAA', lambda table, key, data: self.aaa_handler(key, data))
self.config_db.subscribe('TACPLUS_SERVER', lambda table, key, data: self.tacacs_server_handler(key, data))
self.config_db.subscribe('TACPLUS', lambda table, key, data: self.tacacs_global_handler(key, data))
self.config_db.listen()
def main():
daemon = HostConfigDaemon()
daemon.start()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,11 @@
[Unit]
Description=Host config enforcer daemon
Requires=database.service
After=database.service
[Service]
Type=simple
ExecStart=/usr/bin/hostcfgd
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,25 @@
onfiguration for libnss-tacplus
# debug - If you want to open debug log, set it on
# Default: off
# debug=on
{% if debug %}
debug=on
{% endif %}
# server - set ip address, tcp port, secret string and timeout for TACACS+ servers
# Default: None (no TACACS+ server)
# server=1.1.1.1:49,secret=test,timeout=3
{% for server in servers %}
server={{ server.ip }}:{{ server.tcp_port }},secret={{ server.passkey }},timeout={{ server.timeout }}
{% endfor %}
# user_priv - set the map between TACACS+ user privilege and local user's passwd
# Default:
# user_priv=15;pw_info=remote_user_su;gid=1000;group=sudo,docker;shell=/bin/bash
# user_priv=1;pw_info=remote_user;gid=999;group=docker;shell=/bin/bash
# many_to_one - create one local user for many TACACS+ users which has the same privilege
# Default: many_to_one=n
# many_to_one=y

@ -1 +1 @@
Subproject commit c25b5aecabbb09270dc805459434ee396792ccb3
Subproject commit c763924affd416df9c4d3e40d4f8ac1cb2be5fff

View File

@ -2,7 +2,17 @@
DOCKER_SONIC_P4 = docker-sonic-p4.gz
$(DOCKER_SONIC_P4)_PATH = $(PLATFORM_PATH)/docker-sonic-p4
$(DOCKER_SONIC_P4)_DEPENDS += $(SWSS) $(SYNCD) $(P4_SWITCH) $(REDIS_SERVER) $(REDIS_TOOLS) $(LIBTEAMDCT) $(LIBTEAM_UTILS)
$(DOCKER_SONIC_P4)_DEPENDS += $(SWSS) \
$(SYNCD) \
$(P4_SWITCH) \
$(REDIS_SERVER) \
$(REDIS_TOOLS) \
$(PYTHON_SWSSCOMMON) \
$(LIBTEAMDCT) \
$(LIBTEAM_UTILS) \
$(SONIC_DEVICE_DATA) \
$(SONIC_UTILS) \
$(IPROUTE2)
# ifeq ($(ROUTING_STACK), quagga)
$(DOCKER_SONIC_P4)_DEPENDS += $(QUAGGA)
@ -12,5 +22,8 @@ $(DOCKER_SONIC_P4)_DEPENDS += $(QUAGGA)
# $(DOCKER_SONIC_P4)_DEPENDS += $(GOBGP)
# endif
$(DOCKER_SONIC_P4)_LOAD_DOCKERS += $(DOCKER_BASE)
$(DOCKER_SONIC_P4)_FILES += $(CONFIGDB_LOAD_SCRIPT) \
$(ARP_UPDATE_SCRIPT)
$(DOCKER_SONIC_P4)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE)
SONIC_DOCKER_IMAGES += $(DOCKER_SONIC_P4)

View File

@ -1,11 +1,47 @@
FROM docker-base
FROM docker-config-engine
## Make apt-get non-interactive
ENV DEBIAN_FRONTEND=noninteractive
COPY ["sonic-dev.gpg.key", "/etc/apt/"]
RUN apt-key add /etc/apt/sonic-dev.gpg.key
RUN echo "deb http://packages.microsoft.com/repos/sonic-dev/ jessie main" >> /etc/apt/sources.list
RUN apt-get update
RUN apt-get install -y net-tools ethtool tcpdump ifupdown bridge-utils python-ply libqt5core5a libqt5network5 libboost-program-options1.55.0 libboost-system1.55.0 libboost-thread1.55.0 libgmp10 libjudydebian1 libnanomsg0 libdaemon0 libjansson4 libjemalloc1 openssh-client openssh-server libc-ares2 iproute
RUN apt-get install -y net-tools \
arping \
ethtool \
tcpdump \
ifupdown \
bridge-utils \
python-ply \
libqt5core5a \
libqt5network5 \
libboost-program-options1.55.0 \
libboost-system1.55.0 \
libboost-thread1.55.0 \
libgmp10 \
libjudydebian1 \
libnanomsg0 \
libdaemon0 \
libjansson4 \
libjemalloc1 \
openssh-client \
openssh-server \
libc-ares2 \
iproute \
libpython2.7 \
grub2-common \
python-click-default-group \
python-click \
python-natsort \
python-tabulate \
bash-completion \
libelf1 \
libmnl0
RUN pip install setuptools
RUN pip install py2_ipaddress
COPY \
{% for deb in docker_sonic_p4_debs.split(' ') -%}
@ -18,20 +54,26 @@ RUN dpkg -i \
debs/{{ deb }}{{' '}}
{%- endfor %}
ADD port_config.ini /port_config.ini
ADD startup.sh /scripts/startup.sh
ADD run_bm.sh /scripts/run_bm.sh
ADD rsyslog.conf /etc/rsyslog.conf
## Clean up
RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y
RUN rm -rf /debs
RUN sed -ri 's/^daemonize yes$/daemonize no/; \
RUN sed -ri 's/^(save .*$)/# \1/g; \
s/^daemonize yes$/daemonize no/; \
s/^logfile .*$/logfile ""/; \
s/^# syslog-enabled no$/syslog-enabled no/; \
s/^# unixsocket/unixsocket/ \
s/^# unixsocket/unixsocket/; \
s/notify-keyspace-events ""/notify-keyspace-events AKE/; \
s/^client-output-buffer-limit pubsub [0-9]+mb [0-9]+mb [0-9]+/client-output-buffer-limit pubsub 0 0 0/ \
' /etc/redis/redis.conf
ENTRYPOINT /bin/bash
ADD port_config.ini /port_config.ini
ADD rsyslog.conf /etc/rsyslog.conf
COPY ["start.sh", "orchagent.sh", "config_bm.sh", "/usr/bin/"]
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
COPY ["files/configdb-load.sh", "/usr/bin/"]
COPY ["files/arp_update", "/usr/bin"]
RUN echo "docker-sonic-p4" > /etc/hostname
RUN touch /etc/quagga/zebra.conf
ENTRYPOINT ["/bin/bash"]

View File

@ -0,0 +1,4 @@
simple_switch_CLI --pre SimplePreLAG < /usr/share/p4-sai-bm/bridge_default_config.txt
simple_switch_CLI < /usr/share/p4-sai-bm/bridge_default_config_mirror.txt
simple_switch_CLI --pre SimplePreLAG --thrift-port 9091 < /usr/share/p4-sai-bm/router_default_config.txt
simple_switch_CLI --thrift-port 9091 < /usr/share/p4-sai-bm/router_default_config_mirror.txt

View File

@ -0,0 +1,15 @@
#!/usr/bin/env bash
MAC_ADDRESS=`ip link show eth0 | grep ether | awk '{print $2}'`
# Create a folder for SsWW record files
mkdir -p /var/log/swss
ORCHAGENT_ARGS="-d /var/log/swss "
# Set orchagent pop batch size to 8192
ORCHAGENT_ARGS+="-b 8192 "
# Set mac address
ORCHAGENT_ARGS+="-m $MAC_ADDRESS"
exec /usr/bin/orchagent ${ORCHAGENT_ARGS}

View File

@ -30,9 +30,9 @@ $ModLoad imuxsock # provides support for local system logging
#### GLOBAL DIRECTIVES ####
###########################
#Set remote syslog server
*.* @172.17.0.1:514
#*.* @172.17.0.1:514
#Set local syslog
#*.* /var/log/messages
*.* /var/log/messages
#
# Use traditional timestamp format.

View File

@ -1,23 +0,0 @@
#!/bin/sh
# handler()
# {
# kill -s INT $ROUTER_PID
# kill -s INT $BRIDGE_PID
# }
set -m
ip netns exec sw_net simple_switch -i 0@router_port1 -i 250@router_cpu_port --thrift-port 9091 --log-file /tmp/router_log --log-flush --notifications-addr ipc:///tmp/bmv2-router-notifications.ipc /usr/share/p4-sai-bm/sai_router.json &
export ROUTER_PID=$!
ip netns exec sw_net simple_switch -i 0@sw_port0 -i 1@sw_port1 -i 2@sw_port2 -i 3@sw_port3 -i 4@sw_port4 -i 5@sw_port5 -i 6@sw_port6 -i 7@sw_port7 -i 7@sw_port7 -i 8@sw_port8 -i 9@sw_port9 -i 10@sw_port10 -i 11@sw_port11 -i 12@sw_port12 -i 13@sw_port13 -i 14@sw_port14 -i 15@sw_port15 -i 16@sw_port16 -i 17@sw_port17 -i 18@sw_port18 -i 19@sw_port19 -i 20@sw_port20 -i 21@sw_port21 -i 22@sw_port22 -i 23@sw_port23 -i 24@sw_port24 -i 25@sw_port25 -i 26@sw_port26 -i 27@sw_port27 -i 28@sw_port28 -i 29@sw_port29 -i 30@sw_port30 -i 31@sw_port31 -i 250@cpu_port -i 251@router_port0 --log-file /tmp/bridge_log --log-flush /usr/share/p4-sai-bm/sai_bridge.json &
export BRIDGE_PID=$!
sleep 10
simple_switch_CLI --pre SimplePreLAG < /usr/share/p4-sai-bm/bridge_default_config.txt
simple_switch_CLI < /usr/share/p4-sai-bm/bridge_default_config_mirror.txt
simple_switch_CLI --pre SimplePreLAG --thrift-port 9091 < /usr/share/p4-sai-bm/router_default_config.txt
simple_switch_CLI --thrift-port 9091 < /usr/share/p4-sai-bm/router_default_config_mirror.txt
# echo "router and bridge are running send SIGINT to close"
# trap handler INT
# sleep inf
# sudo kill -s SIGINT 3319

View File

@ -0,0 +1,30 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mQENBFQ1bTIBCAC7oGfkv/ck0XsLuG8cdcSB2ISqxFAcBvH9BitEtxmpW2uhykKk
xY4rVD/4Uys1s3PF1/64QfPR+hYcewueOwz0ZAcLyFXXk4McICXaPq3NrLiWYKKX
UZLnrPzcrGZoW/kHDDp4OmBiDmT1PGvZlpuimwkMCusUzIr7Cbbp2dIy8MERL5tA
LcgLu3KL6clJ+aTW2jgepI1D7sTepOeGd7eRSb5njKg2M7k/93v/7MipZxiVtyXH
B74YiK6jSbst5JpuYsLa/Dqryvx7Xq3n53oif892pv3euTduo1fYw8Hgh/OOYdeT
c9WCj03KA1jCSFURjdrug0kR8BPlfjqtRLXFABEBAAG0JE1TIE9wZW4gVGVjaCA8
aW50ZXJvcEBtaWNyb3NvZnQuY29tPokBOAQTAQIAIgUCVDVtMgIbAwYLCQgHAwIG
FQgCCQoLBBYCAwECHgECF4AACgkQsCxG30F6CJO1uAf/cmL68bM8YgF/61hkaY56
LqrppUTJH/w4fKq47Pf6KfgSLvxfNU6soi2KHYRjIvTRx3tV4vUM5n2plaQg2s8V
/Epg4FeIRTk75YwiHAzLhLnp5cdUaTvC4j4mwxoB6j9Ty+fXJwQ0MvpDhIZb9vM4
GXw/fEQHCT4f3gx4nReeqE+FB2wVHleX9+Lpodu98JyJTKJRBRHYLqy6S+/lyp2W
aBlsI1LOqBcx1uRK24U7duIpbYwIyrx0cafSruqR2GjVdu+imkhHyUn52VbzYhq1
af0rqYiZ1VOamVOG0By8+hVyNa1MLc1K2uWGs0o5fDe9F5/swbvLHVXI+M50Vs+m
J7kBDQRUNW0yAQgAu7DkTVj0ZQC4F7bFivAwrdby8gCakTXOl1kcK622hjRJ8nam
aZeW+eADfLRsTmdUmXgZu1YWS5Gn2ZVngC8SGPUBT071+oRETCz4uNB7IimB9QfP
++orI6o2vmnVVsq5wWCbEdNU+TCVv1zjrYev5lwckkKpjHt6o8MNoX2DFuQymSyR
eZKaqhdKmcji4Ke7OIYqwgPjch3wxzE1b5gNOR/iwxWyjjOffZPLr/VhIfIJRs86
dSXrwjHtEh810SKDLghHM0VAdY34nyC5ZZ61yhts5HtQDFK+9mNpH1mkc4gDBlgG
266pVvknumK6lPNm/osF/cpjWmEw24ypcQIvOQARAQABiQEfBBgBAgAJBQJUNW0y
AhsMAAoJELAsRt9BegiTMBUH/0sZ6gZy7mCTSAYT+NSXLFtGC2zNUVL80SWvfgYm
k9XPVI22MrefZfQ6M01RylyxtWXjRM8UoN8SDKWPpXumzJf831f/7om5zwutaG7b
tjDPYqRKJSbAIFZu2mN+uLrNQ2SV6XK7FoV0dtcrEX9S7RICb6i19D+70+Oh/qgU
R04H1jqS29XBzqAlIzdBoA+sYAwbOIJsSL3YyNQcUv3B5+5yR/bo/L8pnUJt6iuL
nWW+mi7r8gWPHDSrcdYq1TmmlOM7CwZPgWRZzkQPSeZz52Tt7IP47eyGJ09U4PIf
FtMH1ElL2UgHoA/F9Q88e7LkztaTqE59uXWbIYyuSMJVvRU=
=sb3d
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,97 @@
#!/bin/bash -e
# generate configuration
[ -d /etc/sonic ] || mkdir -p /etc/sonic
if ! ip link show eth0 &> /dev/null; then
ip link add eth0 type dummy
fi
SYSTEM_MAC_ADDRESS=$(ip link show eth0 | grep ether | awk '{print $2}')
sonic-cfggen -a '{"DEVICE_METADATA":{"localhost": {"mac": "'$SYSTEM_MAC_ADDRESS'"}}}' --print-data > /etc/sonic/init_cfg.json
if [ -f /etc/sonic/config_db.json ]; then
sonic-cfggen -j /etc/sonic/config_db.json -j /etc/sonic/init_cfg.json --print-data > /tmp/config_db.json
mv /tmp/config_db.json /etc/sonic/config_db.json
else
sonic-cfggen -j /etc/sonic/init_cfg.json --print-data > /etc/sonic/config_db.json
fi
mkdir -p /etc/swss/config.d/
# sonic-cfggen -m /etc/sonic/minigraph.xml -d -t /usr/share/sonic/templates/ipinip.json.j2 > /etc/swss/config.d/ipinip.json
# sonic-cfggen -m /etc/sonic/minigraph.xml -d -t /usr/share/sonic/templates/mirror.json.j2 > /etc/swss/config.d/mirror.json
# sonic-cfggen -m /etc/sonic/minigraph.xml -d -t /usr/share/sonic/templates/ports.json.j2 > /etc/swss/config.d/ports.json
# export platform=`sonic-cfggen -v platform`
rm -f /var/run/rsyslogd.pid
echo "Start rsyslogd"
supervisorctl start rsyslogd
mkdir -p /var/run/redis
echo "Start redis"
supervisorctl start redis-server
echo "Veth Setup"
veth_setup.sh > /tmp/veth_setup.log
echo "Start BM"
rm -rf bm_logs/bridge_log.*
rm -rf bm_logs/router_log.*
rm -rf log.txt
mkdir -p bm_logs
supervisorctl start bm_bridge
supervisorctl start bm_router
sleep 10
echo "BM Default config"
config_bm.sh > /tmp/config_bm.log
/usr/bin/configdb-load.sh
echo "Start syncd"
supervisorctl start syncd
echo "Start orchagent"
supervisorctl start orchagent
echo "Start portsyncd"
supervisorctl start portsyncd
echo "Start intfsyncd"
supervisorctl start intfsyncd
echo "Start neighsyncd"
supervisorctl start neighsyncd
echo "Start teamsyncd"
supervisorctl start teamsyncd
echo "Start fpmsyncd"
supervisorctl start fpmsyncd
echo "Start intfmgrd"
supervisorctl start intfmgrd
echo "Start vlanmgrd"
supervisorctl start vlanmgrd
echo "Start zebra"
supervisorctl start zebra
echo "Start bgpd"
supervisorctl start bgpd
if [ -f /etc/swss/config.d/default_config.json ]; then
swssconfig /etc/swss/config.d/default_config.json
fi
# Start arp_update when VLAN exists
VLAN=`sonic-cfggen -d -v 'VLAN.keys() | join(" ") if VLAN'`
if [ "$VLAN" != "" ]; then
echo "Start arp_update"
supervisorctl start arp_update
fi

View File

@ -1,43 +0,0 @@
#!/bin/bash
echo "Set onie_platform to x86_64-barefoot_p4-r0"
export onie_platform=x86_64-barefoot_p4-r0
echo "Start rsyslog"
rm -f /var/run/rsyslogd.pid
service rsyslog start
echo "Start redis server"
service redis-server start &
sleep 3
redis-cli flushall
echo "Veth setup"
veth_setup.sh > /tmp/veth_setup.log 2>&1
echo "Start BMV2"
/scripts/run_bm.sh > /tmp/run_bm.log 2>&1 &
sleep 15
redis-cli -n 1 set LOGLEVEL DEBUG
echo "Start Syncd"
syncd -N > /tmp/syncd.log 2>&1 &
sleep 10
echo "Start Orchagent"
orchagent $* > /tmp/orchagent.log 2>&1 &
sleep 10
echo "Start Portsyncd"
portsyncd -p /port_config.ini > /tmp/portsyncd.log 2>&1 &
echo "Start Intfsync"
intfsyncd > /tmp/intfsyncd.log 2>&1 &
echo "Start Neighsyncd"
neighsyncd > /tmp/neighsyncd.log 2>&1 &
echo "Start Fpmsyncd"
fpmsyncd > /tmp/fpmsyncd.log 2>&1 &

View File

@ -0,0 +1,141 @@
[supervisord]
logfile_maxbytes=1MB
logfile_backups=2
nodaemon=false
[program:start.sh]
command=/usr/bin/start.sh
priority=1
autostart=true
autorestart=false
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:rsyslogd]
command=/usr/sbin/rsyslogd -n
priority=2
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:bm_router]
command=ip netns exec sw_net simple_switch -i 0@router_port1 -i 250@router_cpu_port --thrift-port 9091 --log-file bm_logs/router_log --log-flush --notifications-addr ipc:///tmp/bmv2-router-notifications.ipc /usr/share/p4-sai-bm/sai_router.json
priority=3
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:bm_bridge]
command=ip netns exec sw_net simple_switch -i 0@sw_port0 -i 1@sw_port1 -i 2@sw_port2 -i 3@sw_port3 -i 4@sw_port4 -i 5@sw_port5 -i 6@sw_port6 -i 7@sw_port7 -i 7@sw_port7 -i 8@sw_port8 -i 9@sw_port9 -i 10@sw_port10 -i 11@sw_port11 -i 12@sw_port12 -i 13@sw_port13 -i 14@sw_port14 -i 15@sw_port15 -i 16@sw_port16 -i 17@sw_port17 -i 18@sw_port18 -i 19@sw_port19 -i 20@sw_port20 -i 21@sw_port21 -i 22@sw_port22 -i 23@sw_port23 -i 24@sw_port24 -i 25@sw_port25 -i 26@sw_port26 -i 27@sw_port27 -i 28@sw_port28 -i 29@sw_port29 -i 30@sw_port30 -i 31@sw_port31 -i 250@cpu_port -i 251@router_port0 --log-file bm_logs/bridge_log --log-flush /usr/share/p4-sai-bm/sai_bridge.json &
priority=3
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:redis-server]
command=/usr/bin/redis-server /etc/redis/redis.conf
priority=4
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:syncd]
command=/usr/bin/syncd -uN
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:orchagent]
command=/usr/bin/orchagent.sh
priority=5
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:portsyncd]
command=/usr/bin/portsyncd -p /port_config.ini
priority=6
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:intfsyncd]
command=/usr/bin/intfsyncd
priority=7
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:neighsyncd]
command=/usr/bin/neighsyncd
priority=8
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:teamsyncd]
command=/usr/bin/teamsyncd
priority=9
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:vlanmgrd]
command=/usr/bin/vlanmgrd
priority=10
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:intfmgrd]
command=/usr/bin/intfmgrd
priority=11
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:zebra]
command=/usr/lib/quagga/zebra -A 127.0.0.1
priority=12
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:bgpd]
command=/usr/lib/quagga/bgpd -A 127.0.0.1 -F
priority=13
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:fpmsyncd]
command=/usr/bin/fpmsyncd
priority=14
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:arp_update]
command=bash -c "/usr/bin/arp_update; sleep 300"
priority=15
autostart=false
autorestart=true
stdout_logfile=syslog
stderr_logfile=syslog

View File

@ -12,14 +12,17 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :
# Clone isc-dhcp repo
git clone https://anonscm.debian.org/cgit/pkg-dhcp/isc-dhcp.git
pushd ./isc-dhcp
git checkout -f debian/$(ISC_DHCP_VERSION)
popd
# Apply patch
patch -p1 < isc-dhcp-$(ISC_DHCP_VERSION)_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch
# Reset HEAD to the commit of the proper tag
# NOTE: Using "git checkout <tag_name>" here detaches our HEAD,
# which stg doesn't like, so we use this method instead
git reset --hard debian/$(ISC_DHCP_VERSION)
# Apply patches
stg init
stg import -s ../patch/series
# Build source and Debian packages
pushd ./isc-dhcp
dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS)
popd

View File

@ -1,442 +0,0 @@
This patch adds the following functionality to dhcrelay in isc-dhcp v4.3.3-6:
* Add customizable Circuit ID and Remote ID fields
* Support for obtaining name of physical interfaces that are part of a bridge interface
diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
--- a/isc-dhcp/relay/dhcrelay.c 2017-11-17 00:36:51.575121900 +0000
+++ b/isc-dhcp/relay/dhcrelay.c 2017-11-17 00:52:51.024607833 +0000
@@ -73,6 +73,8 @@
did not match any known circuit ID. */
int missing_circuit_id = 0; /* Circuit ID option in matching RAI option
was missing. */
+const char *agent_circuit_id_fmt = NULL; /* Circuit ID custom format string. */
+const char *agent_remote_id_fmt = NULL; /* Remote ID custom format string. */
int max_hop_count = 10; /* Maximum hop count */
#ifdef DHCPv6
@@ -120,6 +122,14 @@
char *dhcrelay_sub_id = NULL;
#endif
+struct interface_name_alias_tuple {
+ char if_name[IFNAMSIZ + 1];
+ char if_alias[IFNAMSIZ + 1];
+};
+
+static struct interface_name_alias_tuple *g_interface_name_alias_map = NULL;
+static size_t g_interface_name_alias_map_size = 0;
+
static void do_relay4(struct interface_info *, struct dhcp_packet *,
unsigned int, unsigned int, struct iaddr,
struct hardware *);
@@ -132,6 +142,10 @@
struct interface_info **,
struct dhcp_packet *, unsigned);
+static int load_interface_alias_map(const char *port_alias_map_file_path);
+static int get_interface_alias_by_name(const char *if_name, char *if_alias_out);
+static void free_interface_alias_map(void);
+
static const char copyright[] =
"Copyright 2004-2015 Internet Systems Consortium.";
static const char arr[] = "All rights reserved.";
@@ -140,28 +154,41 @@
static const char url[] =
"For info, please visit https://www.isc.org/software/dhcp/";
+#define DHCRELAY_OPTION82_USAGE \
+"circuit_id/remote_id interpreted sequences are:\n" \
+"\n" \
+" %%%% A single %%\n" \
+" %%h Hostname of device\n" \
+" %%p Alias of interface that generated the request\n" \
+" %%P Hardware address of interface that generated the request\n" \
+" %%C Client hardware address\n" \
+" %%I DHCP relay agent IP Address\n" \
+
#ifdef DHCPv6
#define DHCRELAY_USAGE \
-"Usage: dhcrelay [-4] [-d] [-q] [-a] [-D]\n"\
+"Usage: dhcrelay [-4] [-d] [-q] [-a <circuit_id> <remote_id>] [-D]\n"\
" [-A <length>] [-c <hops>] [-p <port>]\n" \
" [-pf <pid-file>] [--no-pid]\n"\
" [-m append|replace|forward|discard]\n" \
+" [--name-alias-map-file <name-alias-map-file>]\n" \
" [-i interface0 [ ... -i interfaceN]\n" \
" server0 [ ... serverN]\n\n" \
" dhcrelay -6 [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
" [-pf <pid-file>] [--no-pid]\n" \
+" [--name-alias-map-file <name-alias-map-file>]\n" \
" [-s <subscriber-id>]\n" \
" -l lower0 [ ... -l lowerN]\n" \
" -u upper0 [ ... -u upperN]\n" \
" lower (client link): [address%%]interface[#index]\n" \
-" upper (server link): [address%%]interface"
+" upper (server link): [address%%]interface\n\n" DHCRELAY_OPTION82_USAGE
#else
#define DHCRELAY_USAGE \
-"Usage: dhcrelay [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>] [-p <port>]\n" \
-" [-pf <pid-file>] [--no-pid]\n" \
+"Usage: dhcrelay [-d] [-q] [-a <circuit_id> <remote_id>] [-D]\n" \
+" [-A <length>] [-c <hops>] [-p <port>]\n" \
+" [-pf <pid-file>] [--no-pid]\n"\
" [-m append|replace|forward|discard]\n" \
" [-i interface0 [ ... -i interfaceN]\n" \
-" server0 [ ... serverN]\n\n"
+" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE
#endif
static void usage() {
@@ -287,6 +314,15 @@
local_family_set = 1;
local_family = AF_INET;
#endif
+ if (++i == argc)
+ usage();
+
+ if (argv[i] != NULL && argv[i][0] != '-')
+ agent_circuit_id_fmt = argv[i++];
+
+ if (argv[i] != NULL && argv[i][0] != '-')
+ agent_remote_id_fmt = argv[i];
+
add_agent_options = 1;
} else if (!strcmp(argv[i], "-A")) {
#ifdef DHCPv6
@@ -383,6 +419,13 @@
no_dhcrelay_pid = ISC_TRUE;
} else if (!strcmp(argv[i], "--no-pid")) {
no_pid_file = ISC_TRUE;
+ } else if (!strcmp(argv[i], "--name-alias-map-file")) {
+ if (++i == argc)
+ usage();
+ if (load_interface_alias_map(argv[i]) != 0)
+ log_fatal("Failed to load interface name-alias map.");
+ path_dhcrelay_pid = argv[i];
+ no_dhcrelay_pid = ISC_TRUE;
} else if (!strcmp(argv[i], "--version")) {
log_info("isc-dhcrelay-%s", PACKAGE_VERSION);
exit(0);
@@ -602,6 +645,8 @@
dispatch();
/* In fact dispatch() never returns. */
+ free_interface_alias_map();
+
return (0);
}
@@ -690,10 +735,10 @@
&to, htop) < 0) {
++server_packet_errors;
} else {
- log_debug("Forwarded BOOTREPLY for %s to %s",
- print_hw_addr(packet->htype, packet->hlen,
- packet->chaddr),
- inet_ntoa(to.sin_addr));
+ //log_debug("Forwarded BOOTREPLY for %s to %s",
+ // print_hw_addr(packet->htype, packet->hlen,
+ // packet->chaddr),
+ // inet_ntoa(to.sin_addr));
++server_packets_relayed;
}
@@ -732,10 +777,11 @@
&sp->to, NULL) < 0) {
++client_packet_errors;
} else {
- log_debug("Forwarded BOOTREQUEST for %s to %s",
- print_hw_addr(packet->htype, packet->hlen,
- packet->chaddr),
- inet_ntoa(sp->to.sin_addr));
+ //log_debug("Forwarded BOOTREQUEST for %s to %s",
+ // print_hw_addr(packet->htype, packet->hlen,
+ // packet->chaddr),
+ // inet_ntoa(sp->to.sin_addr));
+
++client_packets_relayed;
}
}
@@ -937,6 +983,151 @@
return (-1);
}
+static int
+_bridgefdbquery(const char *hwAddr, char *interface, int *vlanid) {
+
+#define xstr(s) str(s)
+#define str(s) #s
+#define FDB_STRING_LEN 100
+#define FDB_BUFFER_LEN (FDB_STRING_LEN + 1)
+
+/*
+ * Format for sscanf() to read the 1st, 3th, and 5th
+ * space-delimited fields
+ *
+ * bridge fdb show output
+ * 6c:64:1a:00:06:13 dev swp35 vlan 0 master bridge permanent
+ */
+#define FDB_LINE_FORMAT "%" xstr(FDB_STRING_LEN) "s %*s " \
+ "%" xstr(FDB_STRING_LEN) "s %*s %d %*s"
+
+ char cmdstr[FDB_BUFFER_LEN];
+ char buf[FDB_BUFFER_LEN];
+ char macAddr[FDB_BUFFER_LEN];
+
+ if ((interface == NULL) || (vlanid == NULL)) {
+ return 0;
+ }
+ sprintf(cmdstr, "bridge fdb show | grep -m 1 %s", hwAddr);
+ FILE *cmd = popen(cmdstr, "r");
+
+ if (cmd != NULL) {
+ while (fgets(buf, sizeof(buf), cmd)) {
+ sscanf(buf, FDB_LINE_FORMAT, macAddr, interface, vlanid);
+ //log_debug("bridgefdbquery: macAddr:%s interface: %s vlanid %d",
+ // macAddr, interface, *vlanid);
+ }
+ pclose(cmd);
+ return 0;
+ }
+
+ return -1;
+}
+
+/*
+ * Format the message that will be used by circuit_id and remote_id
+ */
+static int
+format_relay_agent_rfc3046_msg(struct interface_info *ip, struct dhcp_packet *packet,
+ const char *format, char *msg, size_t msgn) {
+ size_t len = 0;
+ char hostname[HOST_NAME_MAX + 1] = { 0 };
+ char ifname[IFNAMSIZ + 1] = { 0 };
+ char *buf = msg;
+
+ for ( ; format && *format && len < msgn; ++format) {
+ size_t strn = 0;
+ const char *str = NULL;
+
+ if (*format == '%') {
+ switch (*++format) {
+ case '\0':
+ --format;
+ break;
+
+ case '%': /* A literal '%' */
+ str = "%";
+ break;
+
+ case 'h': /* Hostname */
+ gethostname(hostname, HOST_NAME_MAX);
+ str = hostname;
+ break;
+
+ case 'p': /* Name of interface that we received the request from */
+ /*
+ * Query FDB to identify the exact physical interface only when source MAC address
+ * is present and '20: DHCP relay agent IP address' (giaddr) is not present
+ */
+ if (packet->htype && !packet->giaddr.s_addr) {
+ int ret = 0, vlanid = 0;
+
+ ret = _bridgefdbquery(print_hw_addr(packet->htype, packet->hlen, packet->chaddr),
+ ip->name,
+ &vlanid);
+
+ if (ret < 0) {
+ //log_debug("MAC Address: %s (interface:%s vlan:%d) not found in bridge fdb show",
+ // print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
+ // ip->name,
+ // vlanid);
+
+ strncpy(ifname, ip->name, IFNAMSIZ);
+ }
+ else if (strlen(ip->name) > 0) {
+ // Translate SONiC interface name to vendor alias
+ if (get_interface_alias_by_name(ip->name, ifname) < 0) {
+ log_error("Failed to retrieve alias for interface name '%s'. Defaulting to interface name.", ip->name);
+ strncpy(ifname, ip->name, IFNAMSIZ);
+ }
+
+ //log_debug("Mapped interface name '%s' to alias '%s'", ip->name, ifname);
+
+ //log_debug("Adding option 82 interface alias for MAC Address %s as '%s'",
+ // print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
+ // ifname);
+ }
+
+ str = ifname;
+ }
+ break;
+
+ case 'P': /* Physical address of interface that we received the request from */
+ str = print_hw_addr(ip->hw_address.hbuf[0], ip->hw_address.hlen - 1, &ip->hw_address.hbuf[1]);
+ break;
+
+ case 'C': /* 24: Client hardware address */
+ str = print_hw_addr(packet->htype, packet->hlen, packet->chaddr);
+ break;
+
+ case 'I': /* 20: DHCP relay agent IP address */
+ str = inet_ntoa(packet->giaddr);
+ break;
+
+ default:
+ log_error("Option %%%c is unrecognized and will not be formatted!", *format);
+ continue;
+ }
+
+ if (str)
+ strn = strlen(str);
+ } else {
+ str = format;
+ strn += 1;
+ }
+
+ // Do we have room?
+ if ((strn+len) > msgn) {
+ return 0;
+ }
+
+ memcpy(buf+len, str, strn);
+ len += strn;
+ }
+
+ return len;
+}
+
/*
* Examine a packet to see if it's a candidate to have a Relay
* Agent Information option tacked onto its tail. If it is, tack
@@ -948,6 +1139,8 @@
int is_dhcp = 0, mms;
unsigned optlen;
u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
+ char circuit_id_buf[255] = { '\0', };
+ char remote_id_buf[255] = { '\0', };
/* If we're not adding agent options to packets, we can skip
this. */
@@ -1077,6 +1270,38 @@
op = sp;
#endif
+ /* option82: custom string for circuit_id */
+ if (agent_circuit_id_fmt) {
+ size_t len = 0;
+
+ len = format_relay_agent_rfc3046_msg(ip, packet, agent_circuit_id_fmt,
+ circuit_id_buf, sizeof(circuit_id_buf));
+
+ if (len > 0) {
+ ip->circuit_id = (uint8_t *)circuit_id_buf;
+ ip->circuit_id_len = len;
+
+ //log_debug("Sending on %s option82:circuit_id='%s' (%d)",
+ // ip->name, (char *)ip->circuit_id, ip->circuit_id_len);
+ }
+ }
+
+ /* option82: custom string for remote_id */
+ if (agent_remote_id_fmt) {
+ size_t len = 0;
+
+ len = format_relay_agent_rfc3046_msg(ip, packet, agent_remote_id_fmt,
+ remote_id_buf, sizeof(remote_id_buf));
+
+ if (len > 0) {
+ ip->remote_id = (uint8_t *)remote_id_buf;
+ ip->remote_id_len = len;
+
+ //log_debug("Sending on %s option82:remote_id='%s' (%d)",
+ // ip->name, (char *)ip->remote_id, ip->remote_id_len);
+ }
+ }
+
/* Sanity check. Had better not ever happen. */
if ((ip->circuit_id_len > 255) ||(ip->circuit_id_len < 1))
log_fatal("Circuit ID length %d out of range [1-255] on "
@@ -1102,7 +1327,7 @@
* If not, forward without adding the option.
*/
if (max - sp >= optlen + 3) {
- log_debug("Adding %d-byte relay agent option", optlen + 3);
+ //log_debug("Adding %d-byte relay agent option", optlen + 3);
/* Okay, cons up *our* Relay Agent Information option. */
*sp++ = DHO_DHCP_AGENT_OPTIONS;
@@ -1735,3 +1960,73 @@
exit(0);
}
+
+#define MAX_PORT_CONFIG_LINE_LEN 1024
+
+// Allocates and loads global map g_interface_name_alias_map
+// Also sets global g_interface_name_alias_map_size
+static int
+load_interface_alias_map(const char *port_alias_map_file_path) {
+ int i = 0;
+ FILE *fp = NULL;
+ char line[MAX_PORT_CONFIG_LINE_LEN] = { 0 };
+
+ fp = fopen(port_alias_map_file_path,"r");
+ if (fp == NULL) {
+ log_error("Unable to open %s", port_alias_map_file_path);
+ return -1;
+ }
+
+ g_interface_name_alias_map_size = 0;
+
+ // Count the number of interfaces listed in the file
+ while (fgets(line, sizeof(line), fp)) {
+ g_interface_name_alias_map_size++;
+ }
+
+ // Allocate our map accordingly
+ g_interface_name_alias_map = ((struct interface_name_alias_tuple *)
+ dmalloc((sizeof(struct interface_name_alias_tuple) * g_interface_name_alias_map_size),
+ MDL));
+
+ // Reset file position indicator to beginning of file
+ fseek(fp, 0, SEEK_SET);
+
+ // Every line should contain exactly one name-alias pair
+ while (fgets(line, sizeof(line), fp)) {
+ // Each line should read as "<name><whitespace><alias>"
+ sscanf(line, "%s %s", g_interface_name_alias_map[i].if_name, g_interface_name_alias_map[i].if_alias);
+ i++;
+ }
+
+ fclose(fp);
+
+ log_info("Loaded %d interface name-alias mappings", i);
+
+ return 0;
+}
+
+// Locates alias for port named if_name, copies alias into if_alias_out, up to a
+// max of IFNAMSIZ bytes.
+// Returns 0 on success, -1 on failure
+static int
+get_interface_alias_by_name(const char *if_name, char *if_alias_out) {
+ int i = 0;
+
+ for (i = 0; i < g_interface_name_alias_map_size; i++) {
+ if (strncmp(if_name, g_interface_name_alias_map[i].if_name, IFNAMSIZ) == 0) {
+ strncpy(if_alias_out, g_interface_name_alias_map[i].if_alias, IFNAMSIZ);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+// Frees global map g_interface_name_alias_map
+// Sets g_interface_name_alias_map_size to 0
+static void
+free_interface_alias_map(void) {
+ free(g_interface_name_alias_map);
+ g_interface_name_alias_map_size = 0;
+}

View File

@ -0,0 +1,266 @@
From 42319f1b56ba6362c874cd64383a055ba6498bee Mon Sep 17 00:00:00 2001
From: Joe LeVeque <jolevequ@microsoft.com>
Date: Mon, 11 Dec 2017 23:21:08 +0000
Subject: [PATCH 1/3] Customizable Option 82 circuit ID and remote ID fields
---
relay/dhcrelay.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 147 insertions(+), 25 deletions(-)
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index 15b4997..a26efca 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -73,6 +73,8 @@ int bad_circuit_id = 0; /* Circuit ID option in matching RAI option
did not match any known circuit ID. */
int missing_circuit_id = 0; /* Circuit ID option in matching RAI option
was missing. */
+const char *agent_circuit_id_fmt = NULL; /* Circuit ID custom format string. */
+const char *agent_remote_id_fmt = NULL; /* Remote ID custom format string. */
int max_hop_count = 10; /* Maximum hop count */
#ifdef DHCPv6
@@ -140,9 +142,19 @@ static const char message[] =
static const char url[] =
"For info, please visit https://www.isc.org/software/dhcp/";
+#define DHCRELAY_OPTION82_USAGE \
+"circuit_id/remote_id interpreted sequences are:\n" \
+"\n" \
+" %%%% A single %%\n" \
+" %%h Hostname of device\n" \
+" %%p Name of interface that generated the request\n" \
+" %%P Hardware address of interface that generated the request\n" \
+" %%C Client hardware address\n" \
+" %%I DHCP relay agent IP Address\n" \
+
#ifdef DHCPv6
#define DHCRELAY_USAGE \
-"Usage: dhcrelay [-4] [-d] [-q] [-a] [-D]\n"\
+"Usage: dhcrelay [-4] [-d] [-q] [-a <circuit_id> <remote_id>] [-D]\n"\
" [-A <length>] [-c <hops>] [-p <port>]\n" \
" [-pf <pid-file>] [--no-pid]\n"\
" [-m append|replace|forward|discard]\n" \
@@ -154,14 +166,15 @@ static const char url[] =
" -l lower0 [ ... -l lowerN]\n" \
" -u upper0 [ ... -u upperN]\n" \
" lower (client link): [address%%]interface[#index]\n" \
-" upper (server link): [address%%]interface"
+" upper (server link): [address%%]interface\n\n" DHCRELAY_OPTION82_USAGE
#else
#define DHCRELAY_USAGE \
-"Usage: dhcrelay [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>] [-p <port>]\n" \
-" [-pf <pid-file>] [--no-pid]\n" \
+"Usage: dhcrelay [-d] [-q] [-a <circuit_id> <remote_id>] [-D]\n" \
+" [-A <length>] [-c <hops>] [-p <port>]\n" \
+" [-pf <pid-file>] [--no-pid]\n"\
" [-m append|replace|forward|discard]\n" \
" [-i interface0 [ ... -i interfaceN]\n" \
-" server0 [ ... serverN]\n\n"
+" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE
#endif
static void usage() {
@@ -287,6 +300,15 @@ main(int argc, char **argv) {
local_family_set = 1;
local_family = AF_INET;
#endif
+ if (++i == argc)
+ usage();
+
+ if (argv[i] != NULL && argv[i][0] != '-')
+ agent_circuit_id_fmt = argv[i++];
+
+ if (argv[i] != NULL && argv[i][0] != '-')
+ agent_remote_id_fmt = argv[i];
+
add_agent_options = 1;
} else if (!strcmp(argv[i], "-A")) {
#ifdef DHCPv6
@@ -938,6 +960,80 @@ find_interface_by_agent_option(struct dhcp_packet *packet,
}
/*
+ * Format the message that will be used by circuit_id and remote_id
+ */
+static int
+format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_packet *packet,
+ const char *format, char *msg, size_t msgn) {
+ size_t len = 0;
+ char hostname[HOST_NAME_MAX] = { 0 };
+ char ifname[IFNAMSIZ] = { 0 };
+ char *buf = msg;
+
+ for ( ; format && *format && len < msgn; ++format) {
+ size_t strn = 0;
+ const char *str = NULL;
+
+ if (*format == '%') {
+ switch (*++format) {
+ case '\0':
+ --format;
+ break;
+
+ case '%': /* A literal '%' */
+ str = "%";
+ break;
+
+ case 'h': /* Hostname */
+ gethostname(hostname, HOST_NAME_MAX);
+ hostname[HOST_NAME_MAX - 1] = '\0';
+ str = hostname;
+ break;
+
+ case 'p': /* Name of interface that we received the request from */
+ strncpy(ifname, ip->name, IFNAMSIZ);
+ str = ifname;
+ break;
+
+ case 'P': /* Physical address of interface that we received the request from */
+ str = print_hw_addr(ip->hw_address.hbuf[0], ip->hw_address.hlen - 1, &ip->hw_address.hbuf[1]);
+ break;
+
+ case 'C': /* 24: Client hardware address */
+ str = print_hw_addr(packet->htype, packet->hlen, packet->chaddr);
+ break;
+
+ case 'I': /* 20: DHCP relay agent IP address */
+ str = inet_ntoa(packet->giaddr);
+ break;
+
+ default:
+ log_error("Option %%%c is unrecognized and will not be formatted!", *format);
+ continue;
+ }
+
+ if (str)
+ strn = strlen(str);
+ } else {
+ str = format;
+ strn = 1;
+ }
+
+ // Do we have room?
+ if ((strn+len) >= msgn) {
+ return 0;
+ }
+
+ if (str && strn > 0) {
+ memcpy(buf+len, str, strn);
+ len += strn;
+ }
+ }
+
+ return len;
+}
+
+/*
* Examine a packet to see if it's a candidate to have a Relay
* Agent Information option tacked onto its tail. If it is, tack
* the option on.
@@ -948,6 +1044,9 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
int is_dhcp = 0, mms;
unsigned optlen;
u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
+ char circuit_id_buf[256] = { '\0' };
+ char remote_id_buf[256] = { '\0' };
+ size_t circuit_id_len = 0, remote_id_len = 0;
/* If we're not adding agent options to packets, we can skip
this. */
@@ -1077,24 +1176,47 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
op = sp;
#endif
- /* Sanity check. Had better not ever happen. */
- if ((ip->circuit_id_len > 255) ||(ip->circuit_id_len < 1))
- log_fatal("Circuit ID length %d out of range [1-255] on "
- "%s\n", ip->circuit_id_len, ip->name);
- optlen = ip->circuit_id_len + 2; /* RAI_CIRCUIT_ID + len */
+ /* option82: custom string for circuit_id */
+ if (agent_circuit_id_fmt) {
+ circuit_id_len = format_relay_agent_rfc3046_msg(ip, packet, agent_circuit_id_fmt,
+ circuit_id_buf, sizeof(circuit_id_buf));
+
+ if (circuit_id_len == 0)
+ strncpy(circuit_id_buf, ip->name, sizeof(ip->name));
+
+ //log_debug("Sending on %s option82:circuit_id='%s' (%d)",
+ // ip->name, circuit_id_buf, circuit_id_len);
+ }
+
+ /* option82: custom string for remote_id */
+ if (agent_remote_id_fmt) {
+ remote_id_len = format_relay_agent_rfc3046_msg(ip, packet, agent_remote_id_fmt,
+ remote_id_buf, sizeof(remote_id_buf));
+
+ //log_debug("Sending on %s option82:remote_id='%s' (%d)",
+ // ip->name, remote_id_buf, remote_id_len);
+ }
+
+ /* Sanity check. Had better not ever happen. */
+ if (circuit_id_len > 255 || circuit_id_len < 1)
+ log_fatal("Circuit ID length %d out of range [1-255] on %s\n",
+ circuit_id_len, ip->name);
+
+ optlen = circuit_id_len + 2; // RAI_CIRCUIT_ID + len
if (ip->remote_id) {
- if (ip->remote_id_len > 255 || ip->remote_id_len < 1)
- log_fatal("Remote ID length %d out of range [1-255] "
- "on %s\n", ip->circuit_id_len, ip->name);
- optlen += ip->remote_id_len + 2; /* RAI_REMOTE_ID + len */
+ if (remote_id_len > 255 || remote_id_len < 1)
+ log_fatal("Remote ID length %d out of range [1-255] on %s\n",
+ remote_id_len, ip->name);
+
+ optlen += remote_id_len + 2; // RAI_REMOTE_ID + len
}
- /* We do not support relay option fragmenting(multiple options to
- * support an option data exceeding 255 bytes).
+ /* We do not support relay option fragmenting (multiple options to
+ * support an option data exceeding 255 bytes)
*/
- if ((optlen < 3) ||(optlen > 255))
- log_fatal("Total agent option length(%u) out of range "
+ if (optlen < 3 || optlen > 255)
+ log_fatal("Total agent option length (%u) out of range "
"[3 - 255] on %s\n", optlen, ip->name);
/*
@@ -1102,7 +1224,7 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
* If not, forward without adding the option.
*/
if (max - sp >= optlen + 3) {
- log_debug("Adding %d-byte relay agent option", optlen + 3);
+ //log_debug("Adding %d-byte relay agent option", optlen + 3);
/* Okay, cons up *our* Relay Agent Information option. */
*sp++ = DHO_DHCP_AGENT_OPTIONS;
@@ -1110,16 +1232,16 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
/* Copy in the circuit id... */
*sp++ = RAI_CIRCUIT_ID;
- *sp++ = ip->circuit_id_len;
- memcpy(sp, ip->circuit_id, ip->circuit_id_len);
- sp += ip->circuit_id_len;
+ *sp++ = circuit_id_len;
+ memcpy(sp, circuit_id_buf, circuit_id_len);
+ sp += circuit_id_len;
/* Copy in remote ID... */
if (ip->remote_id) {
*sp++ = RAI_REMOTE_ID;
- *sp++ = ip->remote_id_len;
- memcpy(sp, ip->remote_id, ip->remote_id_len);
- sp += ip->remote_id_len;
+ *sp++ = remote_id_len;
+ memcpy(sp, remote_id_buf, remote_id_len);
+ sp += remote_id_len;
}
} else {
++agent_option_errors;
--
2.1.4

View File

@ -0,0 +1,114 @@
From 18ca48b7c307e1644f653df4c8503f4ce2677f62 Mon Sep 17 00:00:00 2001
From: Joe LeVeque <jolevequ@microsoft.com>
Date: Mon, 11 Dec 2017 23:39:10 +0000
Subject: [PATCH 2/3] Support for obtaining name of physical interface that is
a member of a bridge interface
---
relay/dhcrelay.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 67 insertions(+), 2 deletions(-)
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index a26efca..84ec79d 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -758,6 +758,7 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet,
print_hw_addr(packet->htype, packet->hlen,
packet->chaddr),
inet_ntoa(sp->to.sin_addr));
+
++client_packets_relayed;
}
}
@@ -917,6 +918,7 @@ find_interface_by_agent_option(struct dhcp_packet *packet,
++corrupt_agent_options;
return (-1);
}
+
switch(buf[i]) {
/* Remember where the circuit ID is... */
case RAI_CIRCUIT_ID:
@@ -959,6 +961,47 @@ find_interface_by_agent_option(struct dhcp_packet *packet,
return (-1);
}
+static int
+_bridgefdbquery(const char *hwAddr, char *interface, int *vlanid) {
+
+#define xstr(s) str(s)
+#define str(s) #s
+#define FDB_STRING_LEN 100
+#define FDB_BUFFER_LEN (FDB_STRING_LEN + 1)
+
+/*
+ * Format for sscanf() to read the 1st, 3th, and 5th
+ * space-delimited fields
+ *
+ * bridge fdb show output
+ * 6c:64:1a:00:06:13 dev swp35 vlan 0 master bridge permanent
+ */
+#define FDB_LINE_FORMAT "%" xstr(FDB_STRING_LEN) "s %*s " \
+ "%" xstr(FDB_STRING_LEN) "s %*s %d %*s"
+
+ char cmdstr[FDB_BUFFER_LEN];
+ char buf[FDB_BUFFER_LEN];
+ char macAddr[FDB_BUFFER_LEN];
+
+ if ((interface == NULL) || (vlanid == NULL)) {
+ return 0;
+ }
+ sprintf(cmdstr, "bridge fdb show | grep -m 1 %s", hwAddr);
+ FILE *cmd = popen(cmdstr, "r");
+
+ if (cmd != NULL) {
+ while (fgets(buf, sizeof(buf), cmd)) {
+ sscanf(buf, FDB_LINE_FORMAT, macAddr, interface, vlanid);
+ //log_debug("bridgefdbquery: macAddr:%s interface: %s vlanid %d",
+ // macAddr, interface, *vlanid);
+ }
+ pclose(cmd);
+ return 0;
+ }
+
+ return -1;
+}
+
/*
* Format the message that will be used by circuit_id and remote_id
*/
@@ -991,8 +1034,30 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack
break;
case 'p': /* Name of interface that we received the request from */
- strncpy(ifname, ip->name, IFNAMSIZ);
- str = ifname;
+ /*
+ * Query FDB to identify the exact physical interface only when source MAC address
+ * is present and '20: DHCP relay agent IP address' (giaddr) is not present
+ */
+ if (packet->htype && !packet->giaddr.s_addr) {
+ int ret = 0, vlanid = 0;
+
+ ret = _bridgefdbquery(print_hw_addr(packet->htype, packet->hlen, packet->chaddr),
+ ifname,
+ &vlanid);
+
+ // If we failed to find a physical interface using the source mac, default
+ // to the interface name we received it on.
+ if (ret < 0) {
+ //log_debug("MAC Address: %s (interface:%s vlan:%d) not found in bridge fdb show",
+ // print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
+ // ip->name,
+ // vlanid);
+
+ strncpy(ifname, ip->name, IFNAMSIZ);
+ }
+
+ str = ifname;
+ }
break;
case 'P': /* Physical address of interface that we received the request from */
--
2.1.4

View File

@ -0,0 +1,177 @@
From 3be065305283b90ddfef92a8736221cbf7cf06e0 Mon Sep 17 00:00:00 2001
From: Joe LeVeque <jolevequ@microsoft.com>
Date: Tue, 12 Dec 2017 00:49:09 +0000
Subject: [PATCH 3/3] Support for loading port alias map file to replace
port name with alias in circuit id
---
relay/dhcrelay.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 102 insertions(+), 1 deletion(-)
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index 84ec79d..0b56e2d 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -122,6 +122,14 @@ static void setup_streams(void);
char *dhcrelay_sub_id = NULL;
#endif
+struct interface_name_alias_tuple {
+ char if_name[IFNAMSIZ];
+ char if_alias[IFNAMSIZ];
+};
+
+static struct interface_name_alias_tuple *g_interface_name_alias_map = NULL;
+static size_t g_interface_name_alias_map_size = 0;
+
static void do_relay4(struct interface_info *, struct dhcp_packet *,
unsigned int, unsigned int, struct iaddr,
struct hardware *);
@@ -134,6 +142,10 @@ static int strip_relay_agent_options(struct interface_info *,
struct interface_info **,
struct dhcp_packet *, unsigned);
+static int load_interface_alias_map(const char *port_alias_map_file_path);
+static int get_interface_alias_by_name(const char *if_name, char *if_alias_out);
+static void free_interface_alias_map(void);
+
static const char copyright[] =
"Copyright 2004-2015 Internet Systems Consortium.";
static const char arr[] = "All rights reserved.";
@@ -147,7 +159,7 @@ static const char url[] =
"\n" \
" %%%% A single %%\n" \
" %%h Hostname of device\n" \
-" %%p Name of interface that generated the request\n" \
+" %%p Alias of interface that generated the request\n" \
" %%P Hardware address of interface that generated the request\n" \
" %%C Client hardware address\n" \
" %%I DHCP relay agent IP Address\n" \
@@ -158,10 +170,12 @@ static const char url[] =
" [-A <length>] [-c <hops>] [-p <port>]\n" \
" [-pf <pid-file>] [--no-pid]\n"\
" [-m append|replace|forward|discard]\n" \
+" [--name-alias-map-file <name-alias-map-file>]\n" \
" [-i interface0 [ ... -i interfaceN]\n" \
" server0 [ ... serverN]\n\n" \
" dhcrelay -6 [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
" [-pf <pid-file>] [--no-pid]\n" \
+" [--name-alias-map-file <name-alias-map-file>]\n" \
" [-s <subscriber-id>]\n" \
" -l lower0 [ ... -l lowerN]\n" \
" -u upper0 [ ... -u upperN]\n" \
@@ -405,6 +419,11 @@ main(int argc, char **argv) {
no_dhcrelay_pid = ISC_TRUE;
} else if (!strcmp(argv[i], "--no-pid")) {
no_pid_file = ISC_TRUE;
+ } else if (!strcmp(argv[i], "--name-alias-map-file")) {
+ if (++i == argc)
+ usage();
+ if (load_interface_alias_map(argv[i]) != 0)
+ log_fatal("Failed to load interface name-alias map.");
} else if (!strcmp(argv[i], "--version")) {
log_info("isc-dhcrelay-%s", PACKAGE_VERSION);
exit(0);
@@ -624,6 +643,8 @@ main(int argc, char **argv) {
dispatch();
/* In fact dispatch() never returns. */
+ free_interface_alias_map();
+
return (0);
}
@@ -1056,6 +1077,16 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack
strncpy(ifname, ip->name, IFNAMSIZ);
}
+ // Attempt to translate SONiC interface name to vendor alias
+ if (get_interface_alias_by_name(ip->name, ifname) < 0) {
+ //log_debug("Failed to retrieve alias for interface name '%s'. Defaulting to interface name.", ip->name);
+ strncpy(ifname, ip->name, IFNAMSIZ);
+ }
+ else {
+ //log_debug("Mapped interface name '%s' to alias '%s'. Adding as option 82 interface alias for MAC Address %s",
+ // ip->name, ifname, print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
+ }
+
str = ifname;
}
break;
@@ -1922,3 +1953,73 @@ dhcp_set_control_state(control_object_state_t oldstate,
exit(0);
}
+
+#define MAX_PORT_CONFIG_LINE_LEN 1024
+
+// Allocates and loads global map g_interface_name_alias_map
+// Also sets global g_interface_name_alias_map_size
+static int
+load_interface_alias_map(const char *port_alias_map_file_path) {
+ int i = 0;
+ FILE *fp = NULL;
+ char line[MAX_PORT_CONFIG_LINE_LEN] = { 0 };
+
+ fp = fopen(port_alias_map_file_path,"r");
+ if (fp == NULL) {
+ log_error("Unable to open %s", port_alias_map_file_path);
+ return -1;
+ }
+
+ g_interface_name_alias_map_size = 0;
+
+ // Count the number of interfaces listed in the file
+ while (fgets(line, sizeof(line), fp)) {
+ g_interface_name_alias_map_size++;
+ }
+
+ // Allocate our map accordingly
+ g_interface_name_alias_map = ((struct interface_name_alias_tuple *)
+ dmalloc((sizeof(struct interface_name_alias_tuple) * g_interface_name_alias_map_size),
+ MDL));
+
+ // Reset file position indicator to beginning of file
+ fseek(fp, 0, SEEK_SET);
+
+ // Every line should contain exactly one name-alias pair
+ while (fgets(line, sizeof(line), fp)) {
+ // Each line should read as "<name><whitespace><alias>"
+ sscanf(line, "%s %s", g_interface_name_alias_map[i].if_name, g_interface_name_alias_map[i].if_alias);
+ i++;
+ }
+
+ fclose(fp);
+
+ log_info("Loaded %d interface name-alias mappings", i);
+
+ return 0;
+}
+
+// Locates alias for port named if_name, copies alias into if_alias_out, up to a
+// max of IFNAMSIZ bytes.
+// Returns 0 on success, -1 on failure
+static int
+get_interface_alias_by_name(const char *if_name, char *if_alias_out) {
+ int i = 0;
+
+ for (i = 0; i < g_interface_name_alias_map_size; i++) {
+ if (strncmp(if_name, g_interface_name_alias_map[i].if_name, IFNAMSIZ) == 0) {
+ strncpy(if_alias_out, g_interface_name_alias_map[i].if_alias, IFNAMSIZ);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+// Frees global map g_interface_name_alias_map
+// Sets g_interface_name_alias_map_size to 0
+static void
+free_interface_alias_map(void) {
+ free(g_interface_name_alias_map);
+ g_interface_name_alias_map_size = 0;
+}
--
2.1.4

View File

@ -0,0 +1,4 @@
# This series applies on GIT commit ee3dffdda38a8cfc6ad2005d8d64a165d2a709ba
0001-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch
0002-Support-for-obtaining-name-of-physical-interface-tha.patch
0003-Support-for-loading-port-alias-map-file-to-replace-p.patch

@ -1 +1 @@
Subproject commit 39f1e23cb834255955f5270234c8a72b14c11d6f
Subproject commit bedc2ec1d018333fefe67390fba5b5f65c62ba6f

@ -1 +1 @@
Subproject commit cb8538962815ea82665a4d4b851d50ea0793811d
Subproject commit be91f161b290328773b98f1e21f7feee797ce91c