[DHCP Relay]: Support Multiple VLANs (Separate DHCP Relay Agents, One Per VLAN) (#999)
* [DHCP Relay]: Support new <DhcpRelays> minigraph tag; support multiple VLANs * Don't start dhcrelay in quiet mode so as to get startup output in syslog * Update sonic-cfggen tests to support new '<DhcpRelays>' tag * <DhcpRelays> tag is only present for VLANs which require a DHCP relay agent -- only parse if present * Don't attempt to configure a DHCP relay agent for VLANs without specified DHCP servers * Modify to work with Taoyu's minigraph/DB changes (#942) * Reduce number of DHCP servers in sonic-cfggen unit tests from 4 to 2 * Remove isc-dhcp-relay sample output file from sonic-cfggen test, as we no longer generate that file * Update Option 82 isc-dhcp-relay patch to load all interface name-alias maps into memory once at start instead of calling sonic-cfggen on each packet we relay * Remove executable permission from Jinja2 template * Set max hop count to 1 so that DHCP relay will only relay packets with a hop count of zero * Replace tabs with spaces * Modify overlooked sonic-cfggen call, use Config DB instead of minigraph * Also ensure > 1 VLAN requires a DHCP relay agent before outputting to template * Generate port name-alias map file using sonic-cfggen and parse that in lieu of parsing port_config.ini directly * No longer drop packets with hop count > 0; Instead, drop packets which already contain agent info
This commit is contained in:
parent
1cd9818fe9
commit
1d16a37d48
@ -22,9 +22,7 @@ RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return
|
|||||||
RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y
|
RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y
|
||||||
RUN rm -rf /debs
|
RUN rm -rf /debs
|
||||||
|
|
||||||
COPY ["start.sh", "isc-dhcp-relay.sh", "/usr/bin/"]
|
COPY ["docker_init.sh", "start.sh", "/usr/bin/"]
|
||||||
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
|
COPY ["docker-dhcp-relay.supervisord.conf.j2", "wait_for_intf.sh.j2", "/usr/share/sonic/templates/"]
|
||||||
COPY ["isc-dhcp-relay.j2", "/usr/share/sonic/templates/"]
|
|
||||||
COPY ["wait_for_intf.sh.j2", "/usr/share/sonic/templates/"]
|
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/supervisord"]
|
ENTRYPOINT ["/usr/bin/docker_init.sh"]
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
[supervisord]
|
||||||
|
logfile_maxbytes=1MB
|
||||||
|
logfile_backups=2
|
||||||
|
nodaemon=true
|
||||||
|
|
||||||
|
[program:start.sh]
|
||||||
|
command=/usr/bin/start.sh
|
||||||
|
priority=1
|
||||||
|
autostart=true
|
||||||
|
autorestart=false
|
||||||
|
stdout_logfile=syslog
|
||||||
|
stderr_logfile=syslog
|
||||||
|
|
||||||
|
[program:rsyslogd]
|
||||||
|
command=/usr/sbin/rsyslogd -n
|
||||||
|
priority=2
|
||||||
|
autostart=false
|
||||||
|
autorestart=false
|
||||||
|
stdout_logfile=syslog
|
||||||
|
stderr_logfile=syslog
|
||||||
|
|
||||||
|
{# If our configuration has VLANs... #}
|
||||||
|
{% if VLAN %}
|
||||||
|
{# Count how many VLANs require a DHCP relay agent... #}
|
||||||
|
{% set num_relays = { 'count': 0 } %}
|
||||||
|
{% for vlan_name in VLAN %}
|
||||||
|
{% if VLAN[vlan_name]['dhcp_servers'] %}
|
||||||
|
{% set _dummy = num_relays.update({'count': 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 -%}
|
||||||
|
{%- if VLAN[vlan_name]['dhcp_servers'] -%}
|
||||||
|
{%- if add_preceding_comma.flag %},{% endif -%}
|
||||||
|
{%- set _dummy = add_preceding_comma.update({'flag': True}) -%}
|
||||||
|
isc-dhcp-relay-{{ vlan_name }}
|
||||||
|
{%- endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
|
||||||
|
{# Create a program entry for each DHCP relay agent instance #}
|
||||||
|
{% for vlan_name in VLAN -%}
|
||||||
|
{%- if VLAN[vlan_name]['dhcp_servers'] -%}
|
||||||
|
[program:isc-dhcp-relay-{{ vlan_name }}]
|
||||||
|
command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -i {{ vlan_name }}
|
||||||
|
{%- for (name, prefix) in INTERFACE -%}
|
||||||
|
{%- if prefix | ipv4 %} -i {{ name }}{% endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- for (name, prefix) in PORTCHANNEL_INTERFACE -%}
|
||||||
|
{%- if prefix | ipv4 %} -i {{ name }}{% endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} {{ dhcp_server }}{% endfor %}
|
||||||
|
|
||||||
|
priority=3
|
||||||
|
autostart=false
|
||||||
|
autorestart=false
|
||||||
|
stdout_logfile=syslog
|
||||||
|
stderr_logfile=syslog
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
18
dockers/docker-dhcp-relay/docker_init.sh
Executable file
18
dockers/docker-dhcp-relay/docker_init.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Generate supervisord config file
|
||||||
|
mkdir -p /etc/supervisor/conf.d/
|
||||||
|
sonic-cfggen -d -t /usr/share/sonic/templates/docker-dhcp-relay.supervisord.conf.j2 > /etc/supervisor/conf.d/docker-dhcp-relay.supervisord.conf
|
||||||
|
|
||||||
|
# Generate the script that waits for all interfaces to come up and make it executable
|
||||||
|
sonic-cfggen -d -t /usr/share/sonic/templates/wait_for_intf.sh.j2 > /usr/bin/wait_for_intf.sh
|
||||||
|
chmod +x /usr/bin/wait_for_intf.sh
|
||||||
|
|
||||||
|
# Generate port name-alias map for isc-dhcp-relay to parse. Each line contains one
|
||||||
|
# name-alias pair of the form "<name> <alias>"
|
||||||
|
sonic-cfggen -d --var-json "PORT" | python -c "import sys, json, os; [sys.stdout.write('%s %s\n' % (k, v['alias'] if 'alias' in v else k)) for (k, v) in json.load(sys.stdin).iteritems()]" > /tmp/port-name-alias-map.txt
|
||||||
|
|
||||||
|
# The docker container should start this script as PID 1, so now that supervisord is
|
||||||
|
# properly configured, we exec supervisord so that it runs as PID 1 for the
|
||||||
|
# duration of the container's lifetime
|
||||||
|
exec /usr/bin/supervisord
|
@ -1,28 +0,0 @@
|
|||||||
SERVERS="{{ DHCP_SERVER | join(' ') }}"
|
|
||||||
|
|
||||||
INTERFACES="
|
|
||||||
{%- set add_preceding_space = { 'flag': False } %}
|
|
||||||
{%- for (name, prefix) in INTERFACE %}
|
|
||||||
{%- if prefix | ipv4 %}
|
|
||||||
{%- if add_preceding_space.flag %} {% endif %}
|
|
||||||
{{ name }}
|
|
||||||
{%- set _dummy = add_preceding_space.update({'flag': True}) %}
|
|
||||||
{%- endif %}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- for (name, prefix) in VLAN_INTERFACE %}
|
|
||||||
{%- if prefix | ipv4 %}
|
|
||||||
{%- if add_preceding_space.flag %} {% endif %}
|
|
||||||
{{ name }}
|
|
||||||
{%- set _dummy = add_preceding_space.update({'flag': True}) %}
|
|
||||||
{%- endif %}
|
|
||||||
{%- endfor %}
|
|
||||||
{%- for (name, prefix) in PORTCHANNEL_INTERFACE %}
|
|
||||||
{%- if prefix | ipv4 %}
|
|
||||||
{%- if add_preceding_space.flag %} {% endif %}
|
|
||||||
{{ name }}
|
|
||||||
{%- set _dummy = add_preceding_space.update({'flag': True}) %}
|
|
||||||
{%- endif %}
|
|
||||||
{%- endfor %}"
|
|
||||||
|
|
||||||
# '-a' option provides option 82 circuit_id and remote_id information
|
|
||||||
OPTIONS="-a %h:%p %P"
|
|
@ -1,18 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Based off /etc/init.d/isc-dhcp-relay
|
|
||||||
#
|
|
||||||
|
|
||||||
# Read init script configuration (interfaces the daemon should listen on
|
|
||||||
# and the DHCP server we should forward requests to.)
|
|
||||||
[ -f /etc/default/isc-dhcp-relay ] && . /etc/default/isc-dhcp-relay
|
|
||||||
|
|
||||||
# Build command line for interfaces (will be passed to dhrelay below.)
|
|
||||||
IFCMD=""
|
|
||||||
if test "$INTERFACES" != ""; then
|
|
||||||
for I in $INTERFACES; do
|
|
||||||
IFCMD=${IFCMD}"-i "${I}" "
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec /usr/sbin/dhcrelay -d -q ${OPTIONS} ${IFCMD} ${SERVERS}
|
|
@ -1,16 +1,13 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Create isc-dhcp-relay config file
|
# Remove stale rsyslog PID file if it exists
|
||||||
sonic-cfggen -d -t /usr/share/sonic/templates/isc-dhcp-relay.j2 > /etc/default/isc-dhcp-relay
|
|
||||||
|
|
||||||
rm -f /var/run/rsyslogd.pid
|
rm -f /var/run/rsyslogd.pid
|
||||||
|
|
||||||
|
# Start rsyslog
|
||||||
supervisorctl start rsyslogd
|
supervisorctl start rsyslogd
|
||||||
|
|
||||||
# Wait for all interfaces to come up before starting the DHCP relay
|
# Wait for all interfaces to come up before starting the DHCP relay agent(s)
|
||||||
sonic-cfggen -d -t /usr/share/sonic/templates/wait_for_intf.sh.j2 > /usr/bin/wait_for_intf.sh
|
|
||||||
chmod +x /usr/bin/wait_for_intf.sh
|
|
||||||
/usr/bin/wait_for_intf.sh
|
/usr/bin/wait_for_intf.sh
|
||||||
|
|
||||||
# Start the DHCP relay
|
# Start the DHCP relay agent(s)
|
||||||
supervisorctl start isc-dhcp-relay
|
supervisorctl start isc-dhcp-relay:*
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
[supervisord]
|
|
||||||
logfile_maxbytes=1MB
|
|
||||||
logfile_backups=2
|
|
||||||
nodaemon=true
|
|
||||||
|
|
||||||
[program:start.sh]
|
|
||||||
command=/usr/bin/start.sh
|
|
||||||
priority=1
|
|
||||||
autostart=true
|
|
||||||
autorestart=false
|
|
||||||
stdout_logfile=syslog
|
|
||||||
stderr_logfile=syslog
|
|
||||||
|
|
||||||
[program:rsyslogd]
|
|
||||||
command=/usr/sbin/rsyslogd -n
|
|
||||||
priority=2
|
|
||||||
autostart=false
|
|
||||||
autorestart=false
|
|
||||||
stdout_logfile=syslog
|
|
||||||
stderr_logfile=syslog
|
|
||||||
|
|
||||||
[program:isc-dhcp-relay]
|
|
||||||
command=/usr/bin/isc-dhcp-relay.sh
|
|
||||||
priority=3
|
|
||||||
autostart=false
|
|
||||||
autorestart=false
|
|
||||||
stdout_logfile=syslog
|
|
||||||
stderr_logfile=syslog
|
|
1
dockers/docker-dhcp-relay/wait_for_intf.sh.j2
Executable file → Normal file
1
dockers/docker-dhcp-relay/wait_for_intf.sh.j2
Executable file → Normal file
@ -25,4 +25,3 @@ wait_until_iface_exists {{ name }}
|
|||||||
{% for (name, prefix) in PORTCHANNEL_INTERFACE %}
|
{% for (name, prefix) in PORTCHANNEL_INTERFACE %}
|
||||||
wait_until_iface_exists {{ name }}
|
wait_until_iface_exists {{ name }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
This patch adds the following functionality to dhcrelay in isc-dhcp v4.3.1-6:
|
This patch adds the following functionality to dhcrelay in isc-dhcp v4.3.1-6:
|
||||||
* Add customizable Circuit ID and Remote ID fields
|
* Add customizable Circuit ID and Remote ID fields
|
||||||
* Support for obtaining name of physical interface of interfaces that are part of a bridge interface
|
* 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
|
diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
||||||
--- a/isc-dhcp/relay/dhcrelay.c 2014-08-06 22:35:02.000000000 +0000
|
--- a/isc-dhcp/relay/dhcrelay.c 2017-10-03 01:46:19.811524700 +0000
|
||||||
+++ b/isc-dhcp/relay/dhcrelay.c 2017-06-08 21:39:53.856192546 +0000
|
+++ b/isc-dhcp/relay/dhcrelay.c 2017-10-03 01:45:50.699524700 +0000
|
||||||
@@ -73,6 +73,8 @@
|
@@ -73,6 +73,8 @@
|
||||||
did not match any known circuit ID. */
|
did not match any known circuit ID. */
|
||||||
int missing_circuit_id = 0; /* Circuit ID option in matching RAI option
|
int missing_circuit_id = 0; /* Circuit ID option in matching RAI option
|
||||||
@ -14,7 +14,33 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
int max_hop_count = 10; /* Maximum hop count */
|
int max_hop_count = 10; /* Maximum hop count */
|
||||||
|
|
||||||
#ifdef DHCPv6
|
#ifdef DHCPv6
|
||||||
@@ -140,9 +142,19 @@
|
@@ -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-2014 Internet Systems Consortium.";
|
||||||
|
static const char arr[] = "All rights reserved.";
|
||||||
|
@@ -140,28 +154,42 @@
|
||||||
static const char url[] =
|
static const char url[] =
|
||||||
"For info, please visit https://www.isc.org/software/dhcp/";
|
"For info, please visit https://www.isc.org/software/dhcp/";
|
||||||
|
|
||||||
@ -23,7 +49,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
+"\n" \
|
+"\n" \
|
||||||
+" %%%% A single %%\n" \
|
+" %%%% A single %%\n" \
|
||||||
+" %%h Hostname of device\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" \
|
+" %%P Hardware address of interface that generated the request\n" \
|
||||||
+" %%C Client hardware address\n" \
|
+" %%C Client hardware address\n" \
|
||||||
+" %%I DHCP relay agent IP Address\n" \
|
+" %%I DHCP relay agent IP Address\n" \
|
||||||
@ -35,7 +61,13 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
||||||
" [-pf <pid-file>] [--no-pid]\n"\
|
" [-pf <pid-file>] [--no-pid]\n"\
|
||||||
" [-m append|replace|forward|discard]\n" \
|
" [-m append|replace|forward|discard]\n" \
|
||||||
@@ -154,14 +166,15 @@
|
+" [--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" \
|
" -l lower0 [ ... -l lowerN]\n" \
|
||||||
" -u upper0 [ ... -u upperN]\n" \
|
" -u upper0 [ ... -u upperN]\n" \
|
||||||
" lower (client link): [address%%]interface[#index]\n" \
|
" lower (client link): [address%%]interface[#index]\n" \
|
||||||
@ -49,13 +81,14 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
+" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
+" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
||||||
+" [-pf <pid-file>] [--no-pid]\n"\
|
+" [-pf <pid-file>] [--no-pid]\n"\
|
||||||
" [-m append|replace|forward|discard]\n" \
|
" [-m append|replace|forward|discard]\n" \
|
||||||
|
+" [--name-alias-map-file <name-alias-map-file>]\n" \
|
||||||
" [-i interface0 [ ... -i interfaceN]\n" \
|
" [-i interface0 [ ... -i interfaceN]\n" \
|
||||||
-" server0 [ ... serverN]\n\n"
|
-" server0 [ ... serverN]\n\n"
|
||||||
+" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE
|
+" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void usage() {
|
static void usage() {
|
||||||
@@ -287,6 +300,15 @@
|
@@ -287,6 +315,15 @@
|
||||||
local_family_set = 1;
|
local_family_set = 1;
|
||||||
local_family = AF_INET;
|
local_family = AF_INET;
|
||||||
#endif
|
#endif
|
||||||
@ -71,7 +104,59 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
add_agent_options = 1;
|
add_agent_options = 1;
|
||||||
} else if (!strcmp(argv[i], "-A")) {
|
} else if (!strcmp(argv[i], "-A")) {
|
||||||
#ifdef DHCPv6
|
#ifdef DHCPv6
|
||||||
@@ -937,6 +959,166 @@
|
@@ -383,6 +420,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 +646,8 @@
|
||||||
|
dispatch();
|
||||||
|
|
||||||
|
/* In fact dispatch() never returns. */
|
||||||
|
+ free_interface_alias_map();
|
||||||
|
+
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -690,10 +736,9 @@
|
||||||
|
&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,10 @@
|
||||||
|
&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 +982,152 @@
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,9 +191,8 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
+ if (cmd != NULL) {
|
+ if (cmd != NULL) {
|
||||||
+ while (fgets(buf, sizeof(buf), cmd)) {
|
+ while (fgets(buf, sizeof(buf), cmd)) {
|
||||||
+ sscanf(buf, FDB_LINE_FORMAT, macAddr, interface, vlanid);
|
+ sscanf(buf, FDB_LINE_FORMAT, macAddr, interface, vlanid);
|
||||||
+ log_debug ("bridgefdbquery: macAddr:%s interface: %s vlanid %d",
|
+ //log_debug("bridgefdbquery: macAddr:%s interface: %s vlanid %d",
|
||||||
+ macAddr,
|
+ // macAddr, interface, *vlanid);
|
||||||
+ interface, *vlanid);
|
|
||||||
+ }
|
+ }
|
||||||
+ pclose(cmd);
|
+ pclose(cmd);
|
||||||
+ return 0;
|
+ return 0;
|
||||||
@ -160,42 +244,29 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
+ &vlanid);
|
+ &vlanid);
|
||||||
+
|
+
|
||||||
+ if (ret < 0) {
|
+ if (ret < 0) {
|
||||||
+ log_debug("MAC Address: %s (interface:%s vlan:%d) not found in bridge fdb show",
|
+ //log_debug("MAC Address: %s (interface:%s vlan:%d) not found in bridge fdb show",
|
||||||
+ print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
|
+ // print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
|
||||||
+ ip->name,
|
+ // ip->name,
|
||||||
+ vlanid);
|
+ // vlanid);
|
||||||
|
+
|
||||||
+ strncpy(ifname, ip->name, IFNAMSIZ);
|
+ strncpy(ifname, ip->name, IFNAMSIZ);
|
||||||
+ }
|
+ }
|
||||||
+ else if (strlen(ip->name) > 0) {
|
+ else if (strlen(ip->name) > 0) {
|
||||||
+ char cmdstr[256] = { 0 };
|
+ // Translate SONiC interface name to vendor alias
|
||||||
+ char cmdout[256] = { 0 };
|
+ 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);
|
||||||
+ log_debug("Adding option 82 interface name for MAC Address: %s as %s",
|
+ strncpy(ifname, ip->name, IFNAMSIZ);
|
||||||
+ print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
|
|
||||||
+ ip->name);
|
|
||||||
+
|
|
||||||
+ // Translate SONiC interface name to vendor alias
|
|
||||||
+ sprintf(cmdstr, "sonic-cfggen -m /etc/sonic/minigraph.xml -v \"minigraph_ports['%s'].alias\"", ip->name);
|
|
||||||
+
|
|
||||||
+ FILE *cmd = popen(cmdstr, "r");
|
|
||||||
+
|
|
||||||
+ if (cmd != NULL) {
|
|
||||||
+ while (fgets(cmdout, sizeof(cmdout), cmd)) {
|
|
||||||
+ // Strip any trailing newline
|
|
||||||
+ if (cmdout[strlen(cmdout) - 1] == '\n')
|
|
||||||
+ cmdout[strlen(cmdout) - 1] = '\0';
|
|
||||||
+
|
|
||||||
+ log_debug ("Retrieved alias %s for interface %s", buf, ip->name);
|
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ pclose(cmd);
|
+ //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);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ strncpy(ifname, cmdout, IFNAMSIZ);
|
+ str = ifname;
|
||||||
+ }
|
+ }
|
||||||
+
|
|
||||||
+ str = ifname;
|
|
||||||
+ }
|
|
||||||
+ break;
|
+ break;
|
||||||
+
|
+
|
||||||
+ case 'P': /* Physical address of interface that we received the request from */
|
+ case 'P': /* Physical address of interface that we received the request from */
|
||||||
@ -238,7 +309,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
/*
|
/*
|
||||||
* Examine a packet to see if it's a candidate to have a Relay
|
* 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
|
* Agent Information option tacked onto its tail. If it is, tack
|
||||||
@@ -948,6 +1130,8 @@
|
@@ -948,6 +1139,8 @@
|
||||||
int is_dhcp = 0, mms;
|
int is_dhcp = 0, mms;
|
||||||
unsigned optlen;
|
unsigned optlen;
|
||||||
u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
|
u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
|
||||||
@ -247,7 +318,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
|
|
||||||
/* If we're not adding agent options to packets, we can skip
|
/* If we're not adding agent options to packets, we can skip
|
||||||
this. */
|
this. */
|
||||||
@@ -1077,6 +1261,38 @@
|
@@ -1077,6 +1270,38 @@
|
||||||
op = sp;
|
op = sp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -262,8 +333,8 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
+ ip->circuit_id = (uint8_t *)circuit_id_buf;
|
+ ip->circuit_id = (uint8_t *)circuit_id_buf;
|
||||||
+ ip->circuit_id_len = len;
|
+ ip->circuit_id_len = len;
|
||||||
+
|
+
|
||||||
+ log_debug("sending on %s option82:circuit_id='%s'(%d)",
|
+ //log_debug("Sending on %s option82:circuit_id='%s' (%d)",
|
||||||
+ ip->name, (char *)ip->circuit_id, ip->circuit_id_len);
|
+ // ip->name, (char *)ip->circuit_id, ip->circuit_id_len);
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
@ -278,12 +349,94 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|||||||
+ ip->remote_id = (uint8_t *)remote_id_buf;
|
+ ip->remote_id = (uint8_t *)remote_id_buf;
|
||||||
+ ip->remote_id_len = len;
|
+ ip->remote_id_len = len;
|
||||||
+
|
+
|
||||||
+ log_debug("sending on %s option82:remote_id='%s'(%d)",
|
+ //log_debug("Sending on %s option82:remote_id='%s' (%d)",
|
||||||
+ ip->name, (char *)ip->remote_id, ip->remote_id_len);
|
+ // ip->name, (char *)ip->remote_id, ip->remote_id_len);
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
/* Sanity check. Had better not ever happen. */
|
/* Sanity check. Had better not ever happen. */
|
||||||
if ((ip->circuit_id_len > 255) ||(ip->circuit_id_len < 1))
|
if ((ip->circuit_id_len > 255) ||(ip->circuit_id_len < 1))
|
||||||
log_fatal("Circuit ID length %d out of range [1-255] on "
|
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;
|
||||||
|
@@ -1726,3 +1951,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;
|
||||||
|
+}
|
||||||
|
@ -175,6 +175,14 @@ def parse_dpg(dpg, hname):
|
|||||||
for i, member in enumerate(vmbr_list):
|
for i, member in enumerate(vmbr_list):
|
||||||
vmbr_list[i] = port_alias_map.get(member, member)
|
vmbr_list[i] = port_alias_map.get(member, member)
|
||||||
vlan_attributes = {'members': vmbr_list, 'vlanid': vlanid}
|
vlan_attributes = {'members': vmbr_list, 'vlanid': vlanid}
|
||||||
|
|
||||||
|
# If this VLAN requires a DHCP relay agent, it will contain a <DhcpRelays> element
|
||||||
|
# containing a list of DHCP server IPs
|
||||||
|
if vintf.find(str(QName(ns, "DhcpRelays"))) is not None:
|
||||||
|
vintfdhcpservers = vintf.find(str(QName(ns, "DhcpRelays"))).text
|
||||||
|
vdhcpserver_list = vintfdhcpservers.split(';')
|
||||||
|
vlan_attributes['dhcp_servers'] = vdhcpserver_list
|
||||||
|
|
||||||
sonic_vlan_name = "Vlan%s" % vlanid
|
sonic_vlan_name = "Vlan%s" % vlanid
|
||||||
vlans[sonic_vlan_name] = vlan_attributes
|
vlans[sonic_vlan_name] = vlan_attributes
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@
|
|||||||
<NoDhcpRelay>False</NoDhcpRelay>
|
<NoDhcpRelay>False</NoDhcpRelay>
|
||||||
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
||||||
<Type i:nil="true"/>
|
<Type i:nil="true"/>
|
||||||
|
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||||
<VlanID>1000</VlanID>
|
<VlanID>1000</VlanID>
|
||||||
<Tag>1000</Tag>
|
<Tag>1000</Tag>
|
||||||
<Subnets>192.168.0.0/27</Subnets>
|
<Subnets>192.168.0.0/27</Subnets>
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
SERVERS="192.0.0.1 192.0.0.2 192.0.0.3 192.0.0.4 192.0.0.5 192.0.0.6 192.0.0.7 192.0.0.8 192.0.0.9 192.0.0.10 192.0.0.11 192.0.0.12 192.0.0.13 192.0.0.14 192.0.0.15 192.0.0.16 192.0.0.17 192.0.0.18 192.0.0.19 192.0.0.20 192.0.0.21 192.0.0.22 192.0.0.23 192.0.0.24 192.0.0.25 192.0.0.26 192.0.0.27 192.0.0.28 192.0.0.29 192.0.0.30 192.0.0.31 192.0.0.32 192.0.0.33 192.0.0.34 192.0.0.35 192.0.0.36 192.0.0.37 192.0.0.38 192.0.0.39 192.0.0.40 192.0.0.41 192.0.0.42 192.0.0.43 192.0.0.44 192.0.0.45 192.0.0.46 192.0.0.47 192.0.0.48"
|
|
||||||
|
|
||||||
INTERFACES="Vlan1000 PortChannel01 PortChannel02 PortChannel03 PortChannel04"
|
|
||||||
|
|
||||||
# '-a' option provides option 82 circuit id information
|
|
||||||
OPTIONS="-a"
|
|
||||||
|
|
@ -130,6 +130,7 @@
|
|||||||
<VlanInterface>
|
<VlanInterface>
|
||||||
<Name>Vlan1000</Name>
|
<Name>Vlan1000</Name>
|
||||||
<AttachTo>fortyGigE0/8</AttachTo>
|
<AttachTo>fortyGigE0/8</AttachTo>
|
||||||
|
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||||
<VlanID>1000</VlanID>
|
<VlanID>1000</VlanID>
|
||||||
<Tag>1000</Tag>
|
<Tag>1000</Tag>
|
||||||
<Subnets>192.168.0.0/27</Subnets>
|
<Subnets>192.168.0.0/27</Subnets>
|
||||||
|
@ -203,6 +203,7 @@
|
|||||||
<NoDhcpRelay>False</NoDhcpRelay>
|
<NoDhcpRelay>False</NoDhcpRelay>
|
||||||
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
||||||
<Type i:nil="true"/>
|
<Type i:nil="true"/>
|
||||||
|
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||||
<VlanID>1000</VlanID>
|
<VlanID>1000</VlanID>
|
||||||
<Tag>1000</Tag>
|
<Tag>1000</Tag>
|
||||||
<Subnets>192.168.0.0/27</Subnets>
|
<Subnets>192.168.0.0/27</Subnets>
|
||||||
|
@ -198,6 +198,7 @@
|
|||||||
<NoDhcpRelay>False</NoDhcpRelay>
|
<NoDhcpRelay>False</NoDhcpRelay>
|
||||||
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
||||||
<Type i:nil="true"/>
|
<Type i:nil="true"/>
|
||||||
|
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||||
<VlanID>1000</VlanID>
|
<VlanID>1000</VlanID>
|
||||||
<Tag>1000</Tag>
|
<Tag>1000</Tag>
|
||||||
<Subnets>192.168.0.0/27</Subnets>
|
<Subnets>192.168.0.0/27</Subnets>
|
||||||
|
@ -206,6 +206,7 @@
|
|||||||
<NoDhcpRelay>False</NoDhcpRelay>
|
<NoDhcpRelay>False</NoDhcpRelay>
|
||||||
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
||||||
<Type i:nil="true"/>
|
<Type i:nil="true"/>
|
||||||
|
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||||
<VlanID>1000</VlanID>
|
<VlanID>1000</VlanID>
|
||||||
<Tag>1000</Tag>
|
<Tag>1000</Tag>
|
||||||
<Subnets>192.168.0.0/27</Subnets>
|
<Subnets>192.168.0.0/27</Subnets>
|
||||||
|
@ -83,7 +83,7 @@ class TestCfgGen(TestCase):
|
|||||||
def test_minigraph_vlans(self):
|
def test_minigraph_vlans(self):
|
||||||
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN'
|
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN'
|
||||||
output = self.run_script(argument)
|
output = self.run_script(argument)
|
||||||
self.assertEqual(output.strip(), "{'Vlan1000': {'members': ['Ethernet8'], 'vlanid': '1000'}}")
|
self.assertEqual(output.strip(), "{'Vlan1000': {'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'members': ['Ethernet8'], 'vlanid': '1000'}}")
|
||||||
|
|
||||||
def test_minigraph_vlan_interfaces(self):
|
def test_minigraph_vlan_interfaces(self):
|
||||||
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()"'
|
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()"'
|
||||||
|
Reference in New Issue
Block a user