Merge remote-tracking branch 'azure/master' into bf-master
This commit is contained in:
commit
e2696683ff
23
.gitignore
vendored
23
.gitignore
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
43
files/image_config/hostcfgd/common-auth-sonic.j2
Normal file
43
files/image_config/hostcfgd/common-auth-sonic.j2
Normal 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)
|
||||
|
172
files/image_config/hostcfgd/hostcfgd
Executable file
172
files/image_config/hostcfgd/hostcfgd
Executable 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()
|
||||
|
11
files/image_config/hostcfgd/hostcfgd.service
Normal file
11
files/image_config/hostcfgd/hostcfgd.service
Normal 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
|
25
files/image_config/hostcfgd/tacplus_nss.conf.j2
Normal file
25
files/image_config/hostcfgd/tacplus_nss.conf.j2
Normal 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
|
@ -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)
|
||||
|
@ -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"]
|
4
platform/p4/docker-sonic-p4/config_bm.sh
Executable file
4
platform/p4/docker-sonic-p4/config_bm.sh
Executable 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
|
15
platform/p4/docker-sonic-p4/orchagent.sh
Executable file
15
platform/p4/docker-sonic-p4/orchagent.sh
Executable 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}
|
@ -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.
|
||||
|
@ -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
|
30
platform/p4/docker-sonic-p4/sonic-dev.gpg.key
Normal file
30
platform/p4/docker-sonic-p4/sonic-dev.gpg.key
Normal 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-----
|
97
platform/p4/docker-sonic-p4/start.sh
Executable file
97
platform/p4/docker-sonic-p4/start.sh
Executable 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
|
@ -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 &
|
141
platform/p4/docker-sonic-p4/supervisord.conf
Normal file
141
platform/p4/docker-sonic-p4/supervisord.conf
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
+}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
4
src/isc-dhcp/patch/series
Normal file
4
src/isc-dhcp/patch/series
Normal 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
|
Loading…
Reference in New Issue
Block a user