ZTP infrastructure changes to support DHCP discovery provisioning data (#3298)

* ZTP infrastructure changes to support DHCP discovery provisioning data

- Dynamically generate DHCP client configuration based on current ZTP state
- Added support to request and process hostname when using DHCPv6
- Do not process graphservice url dhcp option if ZTP is enabled, ZTP service
will process it
- Generate /e/n/i file with all active interfaces seeking address assignment
via DHCP. Only interfaces that are created in Linux will be added to /e/n/i.
Also DHCP is started only on linked up in-band interfaces.

Signed-off-by: Rajendra Dendukuri <rajendra.dendukuri@broadcom.com>
This commit is contained in:
rajendra-dendukuri 2019-12-10 11:16:56 -05:00 committed by lguohan
parent 335514bf87
commit fec80293dd
11 changed files with 172 additions and 42 deletions

View File

@ -392,9 +392,6 @@ set /files/etc/sysctl.conf/net.ipv6.conf.default.keep_addr_on_down 1
set /files/etc/sysctl.conf/net.ipv6.conf.all.keep_addr_on_down 1
set /files/etc/sysctl.conf/net.ipv6.conf.eth0.keep_addr_on_down 1
set /files/etc/sysctl.conf/net.ipv6.conf.eth0.accept_ra_defrtr 0
set /files/etc/sysctl.conf/net.ipv6.conf.eth0.accept_ra 0
set /files/etc/sysctl.conf/net.ipv4.tcp_l3mdev_accept 1
set /files/etc/sysctl.conf/net.ipv4.udp_l3mdev_accept 1
@ -429,10 +426,10 @@ EOF
sudo cp files/dhcp/rfc3442-classless-routes $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d
sudo cp files/dhcp/sethostname $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
sudo cp files/dhcp/sethostname6 $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
sudo cp files/dhcp/graphserviceurl $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
sudo cp files/dhcp/snmpcommunity $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
sudo cp files/dhcp/vrf $FILESYSTEM_ROOT/etc/dhcp/dhclient-exit-hooks.d/
sudo cp files/dhcp/dhclient.conf $FILESYSTEM_ROOT/etc/dhcp/
if [ -f files/image_config/ntp/ntp ]; then
sudo cp ./files/image_config/ntp/ntp $FILESYSTEM_ROOT/etc/init.d/
fi

View File

@ -203,6 +203,12 @@ sudo cp $IMAGE_CONFIGS/interfaces/interfaces-config.sh $FILESYSTEM_ROOT/usr/bin/
sudo cp $IMAGE_CONFIGS/interfaces/*.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/
echo "interfaces-config.service" | sudo tee -a $GENERATED_SERVICE_FILE
# Copy dhcp client configuration template and create an initial configuration
sudo cp files/dhcp/dhclient.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/
j2 files/dhcp/dhclient.conf.j2 | sudo tee $FILESYSTEM_ROOT/etc/dhcp/dhclient.conf
sudo cp files/dhcp/ifupdown2_policy.json $FILESYSTEM_ROOT/etc/network/ifupdown2/policy.d
sudo cp files/dhcp/90-dhcp6-systcl.conf.j2 $FILESYSTEM_ROOT_USR_SHARE_SONIC_TEMPLATES/
# Copy initial interfaces configuration file, will be overwritten on first boot
sudo cp $IMAGE_CONFIGS/interfaces/init_interfaces $FILESYSTEM_ROOT/etc/network/interfaces
sudo mkdir -p $FILESYSTEM_ROOT/etc/network/interfaces.d

View File

@ -0,0 +1,7 @@
{% if MGMT_INTERFACE %}
net.ipv6.conf.eth0.accept_ra_defrtr = 0
net.ipv6.conf.eth0.accept_ra = 0
{% else %}
net.ipv6.conf.eth0.accept_ra_defrtr = 1
net.ipv6.conf.eth0.accept_ra = 1
{% endif %}

View File

@ -1,24 +0,0 @@
# Configuration file for /sbin/dhclient, which is included in Debian's
# dhcp3-client package.
#
# This is a sample configuration file for dhclient. See dhclient.conf's
# man page for more information about the syntax of this file
# and a more comprehensive list of the parameters understood by
# dhclient.
#
# Normally, if the DHCP server provides reasonable information and does
# not leave anything out (like the domain name, for example), then
# few changes must be made to this file, if any.
#
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
option snmp-community code 224 = text;
option minigraph-url code 225 = text;
option acl-url code 226 = text;
send host-name = gethostname();
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, domain-search, host-name,
dhcp6.name-servers, dhcp6.domain-search, interface-mtu,
rfc3442-classless-static-routes, ntp-servers,
snmp-community, minigraph-url, acl-url;

View File

@ -0,0 +1,45 @@
{% block banner %}
# =============== Managed by SONiC Config Engine DO NOT EDIT! ===============
# generated from /usr/share/sonic/templates/dhclient.conf.j2 using sonic-cfggen
# file: /etc/dhcp/dhclient.conf
#
{% endblock banner %}
# Configuration file for /sbin/dhclient, which is included in Debian's
# dhcp3-client package.
#
# This is a sample configuration file for dhclient. See dhclient.conf's
# man page for more information about the syntax of this file
# and a more comprehensive list of the parameters understood by
# dhclient.
#
# Normally, if the DHCP server provides reasonable information and does
# not leave anything out (like the domain name, for example), then
# few changes must be made to this file, if any.
#
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
option snmp-community code 224 = text;
option minigraph-url code 225 = text;
option acl-url code 226 = text;
option tftp-server-name code 66 = text;
option bootfile-name code 67 = text;
option user-class code 77 = text;
option provisioning-script-url code 239 = text;
option dhcp6.user-class code 15 = text;
option dhcp6.provisioning-script-url code 239 = text;
option dhcp6.boot-file-url code 59 = text;
send host-name = gethostname();
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, domain-search, host-name,
dhcp6.name-servers, dhcp6.domain-search, interface-mtu, dhcp6.fqdn,
rfc3442-classless-static-routes, ntp-servers, log-servers,
{%- if ZTP is defined and ZTP_DHCP_DISABLED is not defined -%}bootfile-name, provisioning-script-url, tftp-server-name,
dhcp6.provisioning-script-url, dhcp6.boot-file-url,{%- endif -%}
snmp-community, minigraph-url, acl-url;
{% if ZTP is defined and ZTP_DHCP_DISABLED is not defined %}
send user-class "SONiC-ZTP";
send dhcp6.user-class "SONiC-ZTP";
send dhcp-client-identifier "SONiC##{{ ZTP['mode']['product-name'] }}##{{ ZTP['mode']['serial-no'] }}";
retry 60;
{% endif %}

View File

@ -1,12 +1,14 @@
case $reason in
BOUND|RENEW|REBIND|REBOOT)
if [ -n "$new_minigraph_url" ]; then
echo $new_minigraph_url > /tmp/dhcp_graph_url
else
echo "N/A" > /tmp/dhcp_graph_url
fi
if [ -n "$new_acl_url" ]; then
echo $new_acl_url > /tmp/dhcp_acl_url
fi
;;
esac
if [ ! -e /usr/bin/ztp ] || [ "$(ztp status -c)" = "0:DISABLED" ]; then
case $reason in
BOUND|RENEW|REBIND|REBOOT)
if [ -n "$new_minigraph_url" ]; then
echo $new_minigraph_url > /tmp/dhcp_graph_url
else
echo "N/A" > /tmp/dhcp_graph_url
fi
if [ -n "$new_acl_url" ]; then
echo $new_acl_url > /tmp/dhcp_acl_url
fi
;;
esac
fi

View File

@ -0,0 +1,12 @@
{
"dhcp" : {
"defaults" : {
"dhcp-wait" : "no"
},
"iface_defaults" : {
"eth0" : {
"dhcp6-duid" : "LL"
}
}
}
}

View File

@ -55,8 +55,13 @@ if [ "$RUN" = "yes" ]; then
fi
# set route (ip detects host routes automatically)
ip -4 route add "${net_address}/${net_length}" \
if echo $interface | grep -v Ethernet ; then
ip -4 route add "${net_address}/${net_length}" \
${via_arg} dev "${interface}" table default >/dev/null 2>&1
else
ip -4 route add "${net_address}/${net_length}" \
${via_arg} dev "${interface}" >/dev/null 2>&1
fi
done
fi
fi

14
files/dhcp/sethostname6 Normal file
View File

@ -0,0 +1,14 @@
case $reason in
BOUND6|RENEW6|REBIND6|REBOOT)
current_dhcp6_fqdn=`hostname`
if [ "$current_dhcp6_fqdn" != "$new_dhcp6_fqdn" ] && [ -n "$new_dhcp6_fqdn" ]
then
echo $new_dhcp6_fqdn > /etc/hostname
hostname -F /etc/hostname
sed -i "/\s$current_dhcp6_fqdn$/d" /etc/hosts
sed -i "/\s$new_dhcp6_fqdn$/d" /etc/hosts
echo "127.0.0.1 $new_dhcp6_fqdn" >> /etc/hosts
echo ":: $new_dhcp6_fqdn" >> /etc/hosts
fi
;;
esac

View File

@ -2,10 +2,40 @@
ifdown --force eth0
sonic-cfggen -d -t /usr/share/sonic/templates/interfaces.j2 > /etc/network/interfaces
# Check if ZTP DHCP policy has been installed
if [ -e /etc/network/ifupdown2/policy.d/ztp_dhcp.json ]; then
# Obtain port operational state information
redis-dump -d 0 -k "PORT_TABLE:Ethernet*" -y > /tmp/ztp_port_data.json
if [ $? -ne 0 ] || [ ! -e /tmp/ztp_port_data.json ] || [ "$(cat /tmp/ztp_port_data.json)" = "" ]; then
echo "{}" > /tmp/ztp_port_data.json
fi
# Create an input file with ztp input information
echo "{ \"PORT_DATA\" : $(cat /tmp/ztp_port_data.json) }" > \
/tmp/ztp_input.json
else
echo "{ \"ZTP_DHCP_DISABLED\" : \"true\" }" > /tmp/ztp_input.json
fi
# Create /e/n/i file for existing and active interfaces
sonic-cfggen -d -j /tmp/ztp_input.json -t /usr/share/sonic/templates/interfaces.j2 > /etc/network/interfaces
[ -f /var/run/dhclient.eth0.pid ] && kill `cat /var/run/dhclient.eth0.pid` && rm -f /var/run/dhclient.eth0.pid
[ -f /var/run/dhclient6.eth0.pid ] && kill `cat /var/run/dhclient6.eth0.pid` && rm -f /var/run/dhclient6.eth0.pid
for intf_pid in $(ls -1 /var/run/dhclient*.Ethernet*.pid 2> /dev/null); do
[ -f ${intf_pid} ] && kill `cat ${intf_pid}` && rm -f ${intf_pid}
done
sonic-cfggen -d -j /tmp/ztp_input.json -t /usr/share/sonic/templates/90-dhcp6-systcl.conf.j2 > /etc/sysctl.d/90-dhcp6-systcl.conf
# Read sysctl conf files again
sysctl -p /etc/sysctl.d/90-dhcp6-systcl.conf
sonic-cfggen -d -j /tmp/ztp_input.json -t /usr/share/sonic/templates/dhclient.conf.j2 > /etc/dhcp/dhclient.conf
systemctl restart networking
# Clean-up created files
rm -f /tmp/ztp_input.json /tmp/ztp_port_data.json
ifdown lo && ifup lo

View File

@ -27,6 +27,38 @@ iface lo inet loopback
# The management network interface
auto eth0
{% if (ZTP_DHCP_DISABLED is not defined) and (ZTP is defined) and (ZTP['mode'] is defined and ZTP['mode']['profile'] == 'active') %}
# ZTP out-of-band interface
allow-hotplug eth0
{% if ZTP['mode']['ipv4'] == 'true' %}
iface eth0 inet dhcp
{% endif %}
{% if ZTP['mode']['ipv6'] == 'true' %}
iface eth0 inet6 dhcp
up sysctl net.ipv6.conf.eth0.accept_ra=1
down sysctl net.ipv6.conf.eth0.accept_ra=0
{% endif %}
{% if ZTP['mode']['inband'] == 'true' %}
{% for port in PORT %}
# ZTP in-band interface {{ port }}
auto {{ port }}
allow-hotplug {{ port }}
{% if PORT_DATA['PORT_TABLE:'+port] is defined and PORT_DATA['PORT_TABLE:'+port]['value']['oper_status'] == 'up' %}
{% if ZTP['mode']['ipv4'] == 'true' %}
iface {{ port }} inet dhcp
{% endif %}
{% if ZTP['mode']['ipv6'] == 'true' %}
iface {{ port }} inet6 dhcp
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% else %}
{% if MGMT_INTERFACE %}
{% for (name, prefix) in MGMT_INTERFACE|pfx_filter %}
iface eth0 {{ 'inet' if prefix | ipv4 else 'inet6' }} static
@ -70,6 +102,10 @@ iface eth0 inet dhcp
up cgset -r l3mdev.master-device=mgmt mgmt
down cgdelete -g l3mdev:mgmt
{% endif %}
iface eth0 inet6 dhcp
up sysctl net.ipv6.conf.eth0.accept_ra=1
down sysctl net.ipv6.conf.eth0.accept_ra=0
{% endif %}
{% endif %}
#
source /etc/network/interfaces.d/*