[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 rm -rf /debs
|
||||
|
||||
COPY ["start.sh", "isc-dhcp-relay.sh", "/usr/bin/"]
|
||||
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
|
||||
COPY ["isc-dhcp-relay.j2", "/usr/share/sonic/templates/"]
|
||||
COPY ["wait_for_intf.sh.j2", "/usr/share/sonic/templates/"]
|
||||
COPY ["docker_init.sh", "start.sh", "/usr/bin/"]
|
||||
COPY ["docker-dhcp-relay.supervisord.conf.j2", "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
|
||||
|
||||
# Create isc-dhcp-relay config file
|
||||
sonic-cfggen -d -t /usr/share/sonic/templates/isc-dhcp-relay.j2 > /etc/default/isc-dhcp-relay
|
||||
|
||||
# Remove stale rsyslog PID file if it exists
|
||||
rm -f /var/run/rsyslogd.pid
|
||||
|
||||
# Start rsyslog
|
||||
supervisorctl start rsyslogd
|
||||
|
||||
# Wait for all interfaces to come up before starting the DHCP relay
|
||||
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
|
||||
# Wait for all interfaces to come up before starting the DHCP relay agent(s)
|
||||
/usr/bin/wait_for_intf.sh
|
||||
|
||||
# Start the DHCP relay
|
||||
supervisorctl start isc-dhcp-relay
|
||||
# Start the DHCP relay agent(s)
|
||||
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 %}
|
||||
wait_until_iface_exists {{ name }}
|
||||
{% endfor %}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
This patch adds the following functionality to dhcrelay in isc-dhcp v4.3.1-6:
|
||||
* 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
|
||||
--- a/isc-dhcp/relay/dhcrelay.c 2014-08-06 22:35:02.000000000 +0000
|
||||
+++ b/isc-dhcp/relay/dhcrelay.c 2017-06-08 21:39:53.856192546 +0000
|
||||
--- a/isc-dhcp/relay/dhcrelay.c 2017-10-03 01:46:19.811524700 +0000
|
||||
+++ b/isc-dhcp/relay/dhcrelay.c 2017-10-03 01:45:50.699524700 +0000
|
||||
@@ -73,6 +73,8 @@
|
||||
did not match any known circuit ID. */
|
||||
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 */
|
||||
|
||||
#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[] =
|
||||
"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" \
|
||||
+" %%%% 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" \
|
||||
@ -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" \
|
||||
" [-pf <pid-file>] [--no-pid]\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" \
|
||||
" -u upper0 [ ... -u upperN]\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" \
|
||||
+" [-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"
|
||||
+" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE
|
||||
#endif
|
||||
|
||||
static void usage() {
|
||||
@@ -287,6 +300,15 @@
|
||||
@@ -287,6 +315,15 @@
|
||||
local_family_set = 1;
|
||||
local_family = AF_INET;
|
||||
#endif
|
||||
@ -71,7 +104,59 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
||||
add_agent_options = 1;
|
||||
} else if (!strcmp(argv[i], "-A")) {
|
||||
#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);
|
||||
}
|
||||
|
||||
@ -106,9 +191,8 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
||||
+ 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);
|
||||
+ //log_debug("bridgefdbquery: macAddr:%s interface: %s vlanid %d",
|
||||
+ // macAddr, interface, *vlanid);
|
||||
+ }
|
||||
+ pclose(cmd);
|
||||
+ return 0;
|
||||
@ -149,7 +233,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
||||
+
|
||||
+ case 'p': /* Name of interface that we received the request from */
|
||||
+ /*
|
||||
+ * Query FDB to identify the exact physical interface only when source MAC address
|
||||
+ * 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) {
|
||||
@ -160,42 +244,29 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
||||
+ &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);
|
||||
+ //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) {
|
||||
+ char cmdstr[256] = { 0 };
|
||||
+ char cmdout[256] = { 0 };
|
||||
+
|
||||
+ log_debug("Adding option 82 interface name for MAC Address: %s as %s",
|
||||
+ 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);
|
||||
+ // 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);
|
||||
+ }
|
||||
+
|
||||
+ 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;
|
||||
+
|
||||
+ 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
|
||||
* Agent Information option tacked onto its tail. If it is, tack
|
||||
@@ -948,6 +1130,8 @@
|
||||
@@ -948,6 +1139,8 @@
|
||||
int is_dhcp = 0, mms;
|
||||
unsigned optlen;
|
||||
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
|
||||
this. */
|
||||
@@ -1077,6 +1261,38 @@
|
||||
@@ -1077,6 +1270,38 @@
|
||||
op = sp;
|
||||
#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_len = len;
|
||||
+
|
||||
+ log_debug("sending on %s option82:circuit_id='%s'(%d)",
|
||||
+ ip->name, (char *)ip->circuit_id, ip->circuit_id_len);
|
||||
+ //log_debug("Sending on %s option82:circuit_id='%s' (%d)",
|
||||
+ // 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_len = len;
|
||||
+
|
||||
+ log_debug("sending on %s option82:remote_id='%s'(%d)",
|
||||
+ ip->name, (char *)ip->remote_id, ip->remote_id_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;
|
||||
@@ -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):
|
||||
vmbr_list[i] = port_alias_map.get(member, member)
|
||||
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
|
||||
vlans[sonic_vlan_name] = vlan_attributes
|
||||
|
||||
|
@ -108,6 +108,7 @@
|
||||
<NoDhcpRelay>False</NoDhcpRelay>
|
||||
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
||||
<Type i:nil="true"/>
|
||||
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||
<VlanID>1000</VlanID>
|
||||
<Tag>1000</Tag>
|
||||
<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>
|
||||
<Name>Vlan1000</Name>
|
||||
<AttachTo>fortyGigE0/8</AttachTo>
|
||||
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||
<VlanID>1000</VlanID>
|
||||
<Tag>1000</Tag>
|
||||
<Subnets>192.168.0.0/27</Subnets>
|
||||
|
@ -203,6 +203,7 @@
|
||||
<NoDhcpRelay>False</NoDhcpRelay>
|
||||
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
||||
<Type i:nil="true"/>
|
||||
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||
<VlanID>1000</VlanID>
|
||||
<Tag>1000</Tag>
|
||||
<Subnets>192.168.0.0/27</Subnets>
|
||||
|
@ -198,6 +198,7 @@
|
||||
<NoDhcpRelay>False</NoDhcpRelay>
|
||||
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
||||
<Type i:nil="true"/>
|
||||
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||
<VlanID>1000</VlanID>
|
||||
<Tag>1000</Tag>
|
||||
<Subnets>192.168.0.0/27</Subnets>
|
||||
|
@ -206,6 +206,7 @@
|
||||
<NoDhcpRelay>False</NoDhcpRelay>
|
||||
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
|
||||
<Type i:nil="true"/>
|
||||
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
|
||||
<VlanID>1000</VlanID>
|
||||
<Tag>1000</Tag>
|
||||
<Subnets>192.168.0.0/27</Subnets>
|
||||
|
@ -83,7 +83,7 @@ class TestCfgGen(TestCase):
|
||||
def test_minigraph_vlans(self):
|
||||
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v VLAN'
|
||||
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):
|
||||
argument = '-m "' + self.sample_graph_simple + '" -p "' + self.port_config + '" -v "VLAN_INTERFACE.keys()"'
|
||||
|
Loading…
Reference in New Issue
Block a user