[201911] Add dhcp6relay as dhcprelay submodule (#12052)

This commit is contained in:
kellyyeh 2022-11-07 15:27:52 -08:00 committed by GitHub
parent 7769540f42
commit 757130c027
No account linked to committer's email address
21 changed files with 312 additions and 124 deletions

4
.gitmodules vendored
View File

@ -83,3 +83,7 @@
[submodule "src/sonic-ztp"]
path = src/sonic-ztp
url = https://github.com/sonic-net/sonic-ztp
[submodule "src/dhcprelay"]
path = src/dhcprelay
url = https://github.com/sonic-net/sonic-dhcp-relay.git
branch = 201911

View File

@ -26,6 +26,7 @@ RUN apt-get clean -y && \
COPY ["docker_init.sh", "start.sh", "/usr/bin/"]
COPY ["docker-dhcp-relay.supervisord.conf.j2", "port-name-alias-map.txt.j2", "wait_for_intf.sh.j2", "/usr/share/sonic/templates/"]
COPY ["dhcp-relay.programs.j2", "dhcpv4-relay.agents.j2", "dhcpv6-relay.agents.j2", "dhcp-relay.monitors.j2", "/usr/share/sonic/templates/"]
COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
COPY ["critical_processes", "/etc/supervisor"]

View File

@ -1 +1 @@
group:isc-dhcp-relay
group:dhcp-relay

View File

@ -0,0 +1,63 @@
[group:dhcpmon]
programs=
{%- set add_preceding_comma = { 'flag': False } %}
{% set monitor_instance = { 'flag': False } %}
{% for vlan_name in VLAN_INTERFACE %}
{% if VLAN and vlan_name in VLAN and 'dhcp_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcp_servers']|length > 0 %}
{% set _dummy = monitor_instance.update({'flag': True}) %}
{%- endif %}
{% if monitor_instance.flag %}
{% if add_preceding_comma.flag %},{% endif %}
{% set _dummy = add_preceding_comma.update({'flag': True}) %}
dhcpmon-{{ vlan_name }}
{%- set _dummy = monitor_instance.update({'flag': False}) %}
{%- endif %}
{% endfor %}
{# Create a program entry for each DHCP MONitor instance #}
{% set relay_for_ipv4 = { 'flag': False } %}
{% for vlan_name in VLAN_INTERFACE %}
{# Check DHCPv4 agents #}
{% if VLAN and vlan_name in VLAN and 'dhcp_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcp_servers']|length > 0 %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{% if dhcp_server | ipv4 %}
{% set _dummy = relay_for_ipv4.update({'flag': True}) %}
{% endif %}
{% endfor %}
{% endif %}
{% if relay_for_ipv4.flag %}
[program:dhcpmon-{{ vlan_name }}]
{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #}
command=/usr/sbin/dhcpmon -id {{ vlan_name }}
{#- Dual ToR Option #}
{% if 'subtype' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['subtype'] == 'DualToR' %} -u Loopback0{% endif -%}
{#- We treat all other interfaces as upstream interfaces (-iu), as we only want to listen for replies #}
{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %}
{% if prefix | ipv4 and name != vlan_name %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for (name, prefix) in INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% if MGMT_INTERFACE %}
{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -im {{ name }}{% endif -%}
{% endfor %}
{% endif %}
priority=4
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=
{%- if relay_for_ipv4.flag %}isc-dhcpv4-relay-{{ vlan_name }}:running {% endif %}
{% set _dummy = relay_for_ipv4.update({'flag': False}) %}
{% endif %}
{% endfor %}

View File

@ -0,0 +1,22 @@
[group:dhcp-relay]
programs=
{%- set relay_for_ipv6 = { 'flag': False } %}
{%- set add_preceding_comma = { 'flag': False } %}
{% for vlan_name in VLAN_INTERFACE %}
{# Append DHCPv4 agents #}
{% if VLAN and vlan_name in VLAN and 'dhcp_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcp_servers']|length > 0 %}
{% if add_preceding_comma.flag %},{% endif %}
{% set _dummy = add_preceding_comma.update({'flag': True}) %}
isc-dhcpv4-relay-{{ vlan_name }}
{%- endif %}
{% if DHCP_RELAY and vlan_name in DHCP_RELAY and DHCP_RELAY[vlan_name]['dhcpv6_servers']|length > 0 %}
{% set _dummy = relay_for_ipv6.update({'flag': True}) %}
{%- endif %}
{% endfor %}
{# Append DHCPv6 agents #}
{% if relay_for_ipv6.flag %}
{% if add_preceding_comma.flag %},{% endif %}
{% set _dummy = add_preceding_comma.update({'flag': True}) %}
dhcp6relay
{% endif %}

View File

@ -0,0 +1,41 @@
{# Append DHCPv4 agents #}
{% if VLAN and vlan_name in VLAN and 'dhcp_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcp_servers']|length > 0 %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{% if dhcp_server | ipv4 %}
{% set _dummy = relay_for_ipv4.update({'flag': True}) %}
{% endif %}
{% endfor %}
{% if relay_for_ipv4.flag %}
{% set _dummy = relay_for_ipv4.update({'flag': False}) %}
[program:isc-dhcpv4-relay-{{ vlan_name }}]
{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #}
command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id {{ vlan_name }}
{#- Dual ToR Option #}
{% if 'subtype' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['subtype'] == 'DualToR' %} -U Loopback0 -dt{% endif -%}
{#- si option to use intf addr in relay #}
{% if DEVICE_METADATA['localhost']['deployment_id'] == '8' %} -si{% endif -%}
{#- We treat all other interfaces as upstream interfaces (-iu), as we only want to listen for replies #}
{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %}
{% if prefix | ipv4 and name != vlan_name %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for (name, prefix) in INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{%- if dhcp_server | ipv4 %} {{ dhcp_server }}{% endif -%}
{% endfor %}
priority=3
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=start:exited
{% endif %}
{% endif %}

View File

@ -0,0 +1,24 @@
{# Append DHCPv6 agents #}
{# Create a program entry for each DHCPv6 relay agent instance #}
{% for vlan_name in VLAN_INTERFACE %}
{% if DHCP_RELAY and vlan_name in DHCP_RELAY and 'dhcpv6_servers' in DHCP_RELAY[vlan_name] %}
{% for dhcpv6_server in DHCP_RELAY[vlan_name]['dhcpv6_servers'] %}
{% if dhcpv6_server | ipv6 %}
{% set _dummy = relay_for_ipv6.update({'flag': True}) %}
{% endif %}
{% endfor %}
{% if relay_for_ipv6.flag %}
{% set _dummy = relay_for_ipv6.update({'flag': False}) %}
[program:dhcp6relay]
command=/usr/sbin/dhcp6relay
priority=3
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=start:exited
{% endif %}
{% endif %}
{% endfor %}

View File

@ -41,122 +41,27 @@ dependent_startup_wait_for=rsyslogd:running
{# If our configuration has VLANs... #}
{% if VLAN_INTERFACE %}
{# Count how many VLANs require a DHCP relay agent... #}
{% set num_relays = { 'count': 0 } %}
{% set ipv4_num_relays = { 'count': 0 } %}
{% set ipv6_num_relays = { 'count': 0 } %}
{% for vlan_name in VLAN_INTERFACE %}
{% if VLAN and vlan_name in VLAN and 'dhcp_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcp_servers']|length > 0 %}
{% set _dummy = num_relays.update({'count': num_relays.count + 1}) %}
{% set _dummy = ipv4_num_relays.update({'count': ipv4_num_relays.count + 1}) %}
{% endif %}
{% if DHCP_RELAY and vlan_name in DHCP_RELAY and 'dhcpv6_servers' in DHCP_RELAY[vlan_name] %}
{% set _dummy = ipv6_num_relays.update({'count': ipv6_num_relays.count + 1}) %}
{% endif %}
{% endfor %}
{# If one or more of the VLANs require a DHCP relay agent... #}
{% if num_relays.count > 0 %}
[group:isc-dhcp-relay]
programs=
{%- set add_preceding_comma = { 'flag': False } %}
{% for vlan_name in VLAN_INTERFACE %}
{% if VLAN and vlan_name in VLAN and 'dhcp_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcp_servers']|length > 0 %}
{% if add_preceding_comma.flag %},{% endif %}
{% set _dummy = add_preceding_comma.update({'flag': True}) %}
isc-dhcp-relay-{{ vlan_name }}
{%- endif %}
{% endfor %}
{% if ipv4_num_relays.count > 0 or ipv6_num_relays.count > 0 %}
{% include 'dhcp-relay.programs.j2' %}
{# Create a program entry for each DHCP relay agent instance #}
{% set relay_for_ipv4 = { 'flag': False } %}
{% set relay_for_ipv6 = { 'flag': False } %}
{% for vlan_name in VLAN_INTERFACE %}
{% if VLAN and vlan_name in VLAN and 'dhcp_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcp_servers']|length > 0 %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{% if dhcp_server | ipv4 %}
{% set _dummy = relay_for_ipv4.update({'flag': True}) %}
{% endif %}
{% endfor %}
{% if relay_for_ipv4.flag %}
{% set _dummy = relay_for_ipv4.update({'flag': False}) %}
[program:isc-dhcp-relay-{{ vlan_name }}]
{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #}
command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id {{ vlan_name }}
{#- si option to use intf addr in relay #}
{% if DEVICE_METADATA['localhost']['deployment_id'] == '8' %} -si{% endif -%}
{#- We treat all other interfaces as upstream interfaces (-iu), as we only want to listen for replies #}
{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %}
{% if prefix | ipv4 and name != vlan_name %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for (name, prefix) in INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{%- if dhcp_server | ipv4 %} {{ dhcp_server }}{% endif -%}
{% endfor %}
priority=3
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=start:exited
{% endif %}
{% endif %}
{% endfor %}
[group:dhcpmon]
programs=
{%- set add_preceding_comma = { 'flag': False } %}
{% for vlan_name in VLAN_INTERFACE %}
{% if VLAN and vlan_name in VLAN and 'dhcp_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcp_servers']|length > 0 %}
{% if add_preceding_comma.flag %},{% endif %}
{% set _dummy = add_preceding_comma.update({'flag': True}) %}
dhcpmon-{{ vlan_name }}
{%- endif %}
{% endfor %}
{# Create a program entry for each DHCP MONitor instance #}
{% set relay_for_ipv4 = { 'flag': False } %}
{% for vlan_name in VLAN_INTERFACE %}
{% if VLAN and vlan_name in VLAN and 'dhcp_servers' in VLAN[vlan_name] and VLAN[vlan_name]['dhcp_servers']|length > 0 %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{% if dhcp_server | ipv4 %}
{% set _dummy = relay_for_ipv4.update({'flag': True}) %}
{% endif %}
{% endfor %}
{% if relay_for_ipv4.flag %}
{% set _dummy = relay_for_ipv4.update({'flag': False}) %}
[program:dhcpmon-{{ vlan_name }}]
{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #}
command=/usr/sbin/dhcpmon -id {{ vlan_name }}
{#- We treat all other interfaces as upstream interfaces (-iu), as we only want to listen for replies #}
{% for (name, prefix) in VLAN_INTERFACE|pfx_filter %}
{% if prefix | ipv4 and name != vlan_name %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for (name, prefix) in INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% if MGMT_INTERFACE %}
{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -im {{ name }}{% endif -%}
{% endfor %}
{% endif %}
priority=4
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=isc-dhcp-relay-{{ vlan_name }}:running
{% endif %}
{% endif %}
{% include 'dhcpv4-relay.agents.j2' %}
{% endfor %}
{% include 'dhcpv6-relay.agents.j2' %}
{% include 'dhcp-relay.monitors.j2' %}
{% endif %}
{% endif %}

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash
# If our supervisor config has entries in the "isc-dhcp-relay" group...
if [ $(supervisorctl status | grep -c "^isc-dhcp-relay:") -gt 0 ]; then
if [ $(supervisorctl status | grep -c "^dhcp-relay:") -gt 0 ]; then
# Wait for all interfaces to come up and be assigned IPv4 addresses before
# starting the DHCP relay agent(s). If an interface the relay should listen
# on is down, the relay agent will not start. If an interface the relay

View File

@ -38,3 +38,8 @@ wait_until_iface_ready {{ name }} {{ prefix }}
wait_until_iface_ready {{ name }} {{ prefix }}
{% endif %}
{% endfor %}
# Wait 10 seconds for the rest of interfaces to get added/populated.
# dhcrelay listens on each of the interfaces (in addition to the port
# channels and vlan interfaces)
sleep 10

12
rules/dhcprelay.mk Normal file
View File

@ -0,0 +1,12 @@
# SONiC DHCPV6 RELAY Package
SONIC_DHCPRELAY_VERSION = 1.0.0-0
SONIC_DHCPRELAY_PKG_NAME = dhcp6relay
SONIC_DHCPRELAY = sonic-$(SONIC_DHCPRELAY_PKG_NAME)_$(SONIC_DHCPRELAY_VERSION)_$(CONFIGURED_ARCH).deb
$(SONIC_DHCPRELAY)_DEPENDS = $(LIBSWSSCOMMON) $(LIBHIREDIS) $(LIBSWSSCOMMON_DEV) $(LIBHIREDIS_DEV)
$(SONIC_DHCPRELAY)_SRC_PATH = $(SRC_PATH)/dhcprelay
SONIC_DPKG_DEBS += $(SONIC_DHCPRELAY)
SONIC_DHCPRELAY_DBG = sonic-$(SONIC_DHCPRELAY_PKG_NAME)-dbgsym_$(SONIC_DHCPRELAY_VERSION)_amd64.deb
$(eval $(call add_derived_package,$(SONIC_DHCPRELAY),$(SONIC_DHCPRELAY_DBG)))

View File

@ -6,9 +6,9 @@ DOCKER_DHCP_RELAY_DBG = $(DOCKER_DHCP_RELAY_STEM)-$(DBG_IMAGE_MARK).gz
$(DOCKER_DHCP_RELAY)_PATH = $(DOCKERS_PATH)/$(DOCKER_DHCP_RELAY_STEM)
$(DOCKER_DHCP_RELAY)_DEPENDS += $(ISC_DHCP_RELAY) $(REDIS_TOOLS) $(SONIC_DHCPMON)
$(DOCKER_DHCP_RELAY)_DEPENDS += $(ISC_DHCP_RELAY) $(REDIS_TOOLS) $(LIBSWSSCOMMON) $(SONIC_DHCPMON) $(SONIC_DHCPRELAY)
$(DOCKER_DHCP_RELAY)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_STRETCH)_DBG_DEPENDS)
$(DOCKER_DHCP_RELAY)_DBG_DEPENDS += $(ISC_DHCP_RELAY_DBG)
$(DOCKER_DHCP_RELAY)_DBG_DEPENDS += $(ISC_DHCP_RELAY_DBG) $(SONIC_DHCPRELAY_DBG)
$(DOCKER_DHCP_RELAY)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_STRETCH)_DBG_IMAGE_PACKAGES)

View File

@ -301,7 +301,14 @@ RUN apt-get update && apt-get install -y \
xxd \
# For DHCP Monitor tool
libexplain-dev \
libevent-dev
libevent-dev \
# For dhcp6relay
libboost-dev \
libboost-system-dev \
libboost-thread-dev \
libboost-atomic-dev \
libboost-chrono-dev \
libboost-date-time-dev
## Config dpkg
## install the configuration file if its currently missing

1
src/dhcprelay Submodule

@ -0,0 +1 @@
Subproject commit 04a2d4163940d3f70b2f2af5c69681edd4a1b0e1

View File

@ -355,6 +355,7 @@ def parse_dpg(dpg, hname):
vlanintfs = child.find(str(QName(ns, "VlanInterfaces")))
vlans = {}
vlan_members = {}
dhcp_relay_table = {}
intf_vlan_mbr = defaultdict(list)
for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))):
vlanid = vintf.find(str(QName(ns, "VlanID"))).text
@ -376,6 +377,7 @@ def parse_dpg(dpg, hname):
vlan_members[(sonic_vlan_member_name, vmbr_list[i])] = {'tagging_mode': 'untagged'}
vlan_attributes = {'vlanid': vlanid, 'members': vmbr_list }
dhcp_attributes = {}
# If this VLAN requires a DHCP relay agent, it will contain a <DhcpRelays> element
# containing a list of DHCP server IPs
@ -385,10 +387,18 @@ def parse_dpg(dpg, hname):
vdhcpserver_list = vintfdhcpservers.split(';')
vlan_attributes['dhcp_servers'] = vdhcpserver_list
vintf_node = vintf.find(str(QName(ns, "Dhcpv6Relays")))
if vintf_node is not None and vintf_node.text is not None:
vintfdhcpservers = vintf_node.text
vdhcpserver_list = vintfdhcpservers.split(';')
vlan_attributes['dhcpv6_servers'] = vdhcpserver_list
dhcp_attributes['dhcpv6_servers'] = vdhcpserver_list
sonic_vlan_name = "Vlan%s" % vlanid
if sonic_vlan_name != vintfname:
vlan_attributes['alias'] = vintfname
vlans[sonic_vlan_name] = vlan_attributes
dhcp_relay_table[sonic_vlan_name] = dhcp_attributes
acls = {}
for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
@ -490,7 +500,7 @@ def parse_dpg(dpg, hname):
except:
print >> sys.stderr, "Warning: Ignoring Control Plane ACL %s without type" % aclname
return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni
return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_relay_table, pcs, pc_members, acls, vni
return None, None, None, None, None, None, None, None, None, None
def parse_host_loopback(dpg, hname):
@ -606,6 +616,7 @@ def parse_cpg(cpg, hname, local_devices=[]):
def parse_meta(meta, hname):
syslog_servers = []
dhcp_servers = []
dhcpv6_servers = []
ntp_servers = []
tacacs_servers = []
mgmt_routes = []
@ -648,7 +659,7 @@ def parse_meta(meta, hname):
qos_profile = value
elif name == "ResourceType":
resource_type = value
return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, downstream_subrole, qos_profile, resource_type
return syslog_servers, dhcp_servers, dhcpv6_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, downstream_subrole, qos_profile, resource_type
def parse_linkmeta(meta, hname):
@ -935,6 +946,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
console_ports = {}
syslog_servers = []
dhcp_servers = []
dhcpv6_servers = []
ntp_servers = []
tacacs_servers = []
mgmt_routes = []
@ -977,7 +989,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
for child in root:
if asic_name is None:
if child.tag == str(QName(ns, "DpgDec")):
(intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni) = parse_dpg(child, hostname)
(intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_relay_table, pcs, pc_members, acls, vni) = parse_dpg(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, hostname)
elif child.tag == str(QName(ns, "PngDec")):
@ -985,14 +997,14 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
elif child.tag == str(QName(ns, "UngDec")):
(u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname)
elif child.tag == str(QName(ns, "MetadataDeclaration")):
(syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, downstream_subrole, qos_profile, resource_type) = parse_meta(child, hostname)
(syslog_servers, dhcp_servers, dhcpv6_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region, cloudtype, downstream_subrole, qos_profile, resource_type) = parse_meta(child, hostname)
elif child.tag == str(QName(ns, "LinkMetadataDeclaration")):
linkmetas = parse_linkmeta(child, hostname)
elif child.tag == str(QName(ns, "DeviceInfos")):
(port_speeds_default, port_descriptions) = parse_deviceinfo(child, hwsku)
else:
if child.tag == str(QName(ns, "DpgDec")):
(intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni) = parse_dpg(child, asic_name)
(intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_relay_table, pcs, pc_members, acls, vni) = parse_dpg(child, asic_name)
host_lo_intfs = parse_host_loopback(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, asic_name, local_devices)
@ -1245,6 +1257,8 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
results['DEVICE_NEIGHBOR_METADATA'] = { key:devices[key] for key in devices if key in {device['name'] for device in neighbors.values()} }
results['SYSLOG_SERVER'] = dict((item, {}) for item in syslog_servers)
results['DHCP_SERVER'] = dict((item, {}) for item in dhcp_servers)
results['DHCPv6_SERVER'] = dict((item, {}) for item in dhcpv6_servers)
results['DHCP_RELAY'] = dhcp_relay_table
results['NTP_SERVER'] = dict((item, {}) for item in ntp_servers)
results['TACPLUS_SERVER'] = dict((item, {'priority': '1', 'tcp_port': '49'}) for item in tacacs_servers)
results['ACL_TABLE'] = filter_acl_table_bindings(acls, neighbors, pcs, sub_role)

View File

@ -39,10 +39,11 @@ stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=rsyslogd:running
[group:isc-dhcp-relay]
programs=isc-dhcp-relay-Vlan1000
[group:dhcp-relay]
programs=isc-dhcpv4-relay-Vlan1000,dhcp6relay
[program:isc-dhcp-relay-Vlan1000]
[program:isc-dhcpv4-relay-Vlan1000]
command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id Vlan1000 -iu Vlan2000 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04 -iu PortChannel01 192.0.0.1 192.0.0.2
priority=3
autostart=false
@ -53,6 +54,16 @@ dependent_startup=true
dependent_startup_wait_for=start:exited
[program:dhcp6relay]
command=/usr/sbin/dhcp6relay
priority=3
autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=start:exited
[group:dhcpmon]
programs=dhcpmon-Vlan1000
@ -64,7 +75,6 @@ autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
dependent_startup=true
dependent_startup_wait_for=isc-dhcp-relay-Vlan1000:running
dependent_startup_wait_for=isc-dhcpv4-relay-Vlan1000:running

View File

@ -30,3 +30,7 @@ wait_until_iface_ready PortChannel03 10.0.0.60/31
wait_until_iface_ready PortChannel04 10.0.0.62/31
wait_until_iface_ready PortChannel01 10.0.0.56/31
# Wait 10 seconds for the rest of interfaces to get added/populated.
# dhcrelay listens on each of the interfaces (in addition to the port
# channels and vlan interfaces)
sleep 10

View File

@ -131,10 +131,20 @@
<Name>ab1</Name>
<AttachTo>fortyGigE0/8</AttachTo>
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
<Dhcpv6Relays>fc02:2000::1;fc02:2000::2</Dhcpv6Relays>
<VlanID>1000</VlanID>
<Tag>1000</Tag>
<Subnets>192.168.0.0/27</Subnets>
</VlanInterface>
<VlanInterface>
<Name>ab2</Name>
<AttachTo>fortyGigE0/4</AttachTo>
<DhcpRelays>192.0.0.3;192.0.0.4</DhcpRelays>
<Dhcpv6Relays>fc02:2000::3;fc02:2000::4</Dhcpv6Relays>
<VlanID>2000</VlanID>
<Tag>2000</Tag>
<Subnets>192.168.0.0/27</Subnets>
</VlanInterface>
</VlanInterfaces>
<IPInterfaces>
<IPInterface>

View File

@ -240,6 +240,7 @@
<FhrpProtoType i:nil="true"/>
<Type i:nil="true"/>
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
<Dhcpv6Relays>fc02:2000::1;fc02:2000::2</Dhcpv6Relays>
<VlanID>1000</VlanID>
<Tag>1000</Tag>
<Subnets>192.168.0.0/27</Subnets>

View File

@ -617,3 +617,11 @@ class TestCfgGen(TestCase):
argument = '-a \'{"key1":"value"}\' --var-json INTERFACE'
output = self.run_script(argument)
self.assertEqual(output, '')
def test_minigraph_dhcp(self):
argument = '-m "' + self.sample_graph_simple_case + '" -p "' + self.port_config + '" -v DHCP_RELAY'
output = self.run_script(argument)
self.assertEqual(
output.strip(),
"{'Vlan1000': {'dhcpv6_servers': ['fc02:2000::1', 'fc02:2000::2']}, 'Vlan2000': {'dhcpv6_servers': ['fc02:2000::3', 'fc02:2000::4']}}"
)

View File

@ -82,15 +82,49 @@ class TestCfgGenCaseInsensitive(TestCase):
def test_minigraph_vlans(self):
argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v VLAN'
output = self.run_script(argument)
expected = {
'Vlan1000': {
'alias': 'ab1',
'dhcp_servers': [
'192.0.0.1',
'192.0.0.2'
],
'dhcpv6_servers': [
'fc02:2000::1',
'fc02:2000::2'
],
'vlanid': '1000',
'members': ['Ethernet8']
},
'Vlan2000': {
'alias': 'ab2',
'dhcp_servers': [
'192.0.0.3',
'192.0.0.4'],
'members': ['Ethernet4'],
'dhcpv6_servers': [
'fc02:2000::3',
'fc02:2000::4'],
'vlanid': '2000'
}
}
self.assertEqual(
utils.to_dict(output.strip()),
utils.to_dict("{'Vlan1000': {'alias': 'ab1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '1000', 'members': ['Ethernet8'] }}")
expected
)
def test_minigraph_vlan_members(self):
argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v VLAN_MEMBER'
output = self.run_script(argument)
self.assertEqual(output.strip(), "{('Vlan1000', 'Ethernet8'): {'tagging_mode': 'untagged'}}")
expected = {
'Vlan1000|Ethernet8': {'tagging_mode': 'untagged'},
'Vlan2000|Ethernet4': {'tagging_mode': 'untagged'}
}
self.assertEqual(
utils.to_dict(output.strip()),
expected
)
def test_minigraph_vlan_interfaces(self):
argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()"'
@ -190,3 +224,25 @@ class TestCfgGenCaseInsensitive(TestCase):
self.assertEqual(len(mgmt_intf.keys()), 1)
self.assertTrue(('eth0', 'FC00:1::32/64') in mgmt_intf.keys())
self.assertTrue(ipaddress.IPAddress('fc00:1::1') == mgmt_intf[('eth0', 'FC00:1::32/64')]['gwaddr'])
def test_dhcp_table(self):
argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DHCP_RELAY"'
expected = {
'Vlan1000': {
'dhcpv6_servers': [
"fc02:2000::1",
"fc02:2000::2"
]
},
'Vlan2000': {
'dhcpv6_servers': [
"fc02:2000::3",
"fc02:2000::4"
]
}
}
output = self.run_script(argument)
self.assertEqual(
utils.to_dict(output.strip()),
expected
)