[dhcp-relay]: Modify dhcp relay to pick primary address (#17012)

This is change taken as part of the HLD: sonic-net/SONiC#1470 and this is a follow up on the PR #16827 where in the docker-dhcp we pick the value of primary gateway of the interface from the VLAN_Interface table which has "secondary" flag set in the config_db

Microsoft ADO (number only): 16784946

How did I do it
-  Changes in the j2 file to add a new "-pg" parameter in the dhcpv4-relay.agents.j2, the ip would be retrieved from the config db's vlan_interface table such that the interface which are picked will have secondary field set.

- Changes in isc-dhcp to re-order the addresses of the discovered interface and which has the ip which has the passed parameter.
This commit is contained in:
Shashanka Balakuntala 2023-11-23 04:35:32 +05:30 committed by GitHub
parent aea3c42f29
commit 8b192a1151
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 141 additions and 0 deletions

View File

@ -24,6 +24,9 @@ command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /t
{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %} {% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%} {% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %} {% endfor %}
{% for (name, gateway) in VLAN_INTERFACE|get_primary_addr %}
{% if gateway | ipv4 and name == vlan_name %} -pg {{ gateway }}{% endif -%}
{% endfor %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} {% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{%- if dhcp_server | ipv4 %} {{ dhcp_server }}{% endif -%} {%- if dhcp_server | ipv4 %} {{ dhcp_server }}{% endif -%}
{% endfor %} {% endfor %}

View File

@ -0,0 +1,114 @@
diff --git a/common/discover.c b/common/discover.c
index ab50234..40e13f5 100644
--- a/common/discover.c
+++ b/common/discover.c
@@ -1614,3 +1614,16 @@ void interface_snorf (struct interface_info *tmp, int ir)
}
interface_reference (&interfaces, tmp, MDL);
}
+
+void set_primary_addr_in_intf (struct in_addr primary_addr) {
+ for (struct interface_info *tmp = interfaces; tmp; tmp = tmp->next) {
+ for (int i = 0; i < tmp->address_count; i++) {
+ if (tmp->addresses[i].s_addr == primary_addr.s_addr) {
+ struct in_addr tmp_ip = tmp->addresses[0];
+ tmp->addresses[0] = primary_addr;
+ tmp->addresses[i] = tmp_ip;
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index 257b31e..e7f9f06 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -2873,6 +2873,7 @@ extern int interface_count;
extern int interface_max;
isc_result_t interface_initialize(omapi_object_t *, const char *, int);
void discover_interfaces(int);
+void set_primary_addr_in_intf (struct in_addr );
int setup_fallback (struct interface_info **, const char *, int);
int if_readsocket (omapi_object_t *);
void reinitialize_interfaces (void);
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index ff0ad17..31fe61b 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -92,6 +92,11 @@ struct downstream_intf_list {
struct interface_info *interface;
} *downstream_intfs = NULL;
+struct primary_gw_list {
+ struct primary_gw_list *next;
+ struct in_addr gateway_addr;
+} *primary_gws = NULL;
+
#ifdef DHCPv6
/* Force use of DHCPv6 interface-id option. */
isc_boolean_t use_if_id = ISC_FALSE;
@@ -199,6 +204,7 @@ char *progname;
" [-i interface0 [ ... -i interfaceN]\n" \
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
+" [-pg ip-address0 [ ... -pg ip-addressN]]\n" \
" [-U interface]\n" \
" [-dt]\n"\
" server0 [ ... serverN]\n\n" \
@@ -221,6 +227,7 @@ char *progname;
" [-i interface0 [ ... -i interfaceN]\n" \
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
+" [-pg ip-address0 [ ... -pg ip-addressN]]\n" \
" [-U interface]\n" \
" [-dt]\n"\
" server0 [ ... serverN]\n\n" \
@@ -649,6 +656,34 @@ main(int argc, char **argv) {
usage(use_noarg, argv[i-1]);
path_dhcrelay_pid = argv[i];
no_dhcrelay_pid = ISC_TRUE;
+ } else if (!strcmp(argv[i], "-pg")) {
+ if (++i == argc)
+ usage(use_noarg, argv[i-1]);
+#ifdef DHCPv6
+ if (local_family_set && (local_family == AF_INET6)) {
+ usage(use_v4command, argv[i]);
+ }
+ local_family_set = 1;
+ local_family = AF_INET;
+#endif
+ struct in_addr gw = {0};
+ if (inet_pton(AF_INET, argv[i], &gw) <= 0) {
+ usage("Invalid gateway address '%s'", argv[i]);
+ } else {
+ struct primary_gw_list *pg = ((struct primary_gw_list *)dmalloc(sizeof(struct primary_gw_list), MDL));
+ pg->gateway_addr = gw;
+ pg->next = NULL;
+
+ if (primary_gws == NULL) {
+ primary_gws = pg;
+ } else {
+ struct primary_gw_list *tmp = primary_gws;
+ while (tmp->next != NULL) {
+ tmp = tmp->next;
+ }
+ tmp->next = pg;
+ }
+ }
} else if (!strcmp(argv[i], "--no-pid")) {
no_pid_file = ISC_TRUE;
} else if (!strcmp(argv[i], "--name-alias-map-file")) {
@@ -818,6 +853,12 @@ main(int argc, char **argv) {
/* Discover all the network interfaces. */
discover_interfaces(DISCOVER_RELAY);
+ struct primary_gw_list *tmp = primary_gws;
+ while (tmp != NULL) {
+ set_primary_addr_in_intf(tmp->gateway_addr);
+ tmp = tmp->next;
+ }
+
#ifdef DHCPv6
if (local_family == AF_INET6)
setup_streams();

View File

@ -13,3 +13,4 @@
0012-add-option-si-to-support-using-src-intf-ip-in-relay.patch 0012-add-option-si-to-support-using-src-intf-ip-in-relay.patch
0013-Fix-dhcrelay-agent-option-buffer-pointer-logic.patch 0013-Fix-dhcrelay-agent-option-buffer-pointer-logic.patch
0014-enable-parallel-build.patch 0014-enable-parallel-build.patch
0015-option-to-set-primary-address-in-interface.patch

View File

@ -25,6 +25,7 @@ import netaddr
import os import os
import sys import sys
import yaml import yaml
import ipaddress
from collections import OrderedDict from collections import OrderedDict
from config_samples import generate_sample_config, get_available_config from config_samples import generate_sample_config, get_available_config
@ -137,6 +138,27 @@ def ip_network(value):
return "Invalid ip address %s" % value return "Invalid ip address %s" % value
return r_v.network return r_v.network
def get_primary_addr(value):
if not value:
return ""
table = pfx_filter(value)
primary_gateways = OrderedDict()
intf_with_secondary = set()
for key, val in table.items():
name, prefix = key
if "secondary" in val:
intf_with_secondary.add(name)
for key, val in table.items():
name, prefix = key
if name in intf_with_secondary and "secondary" not in val:
if PY3x:
network_def = ipaddress.ip_network(prefix, strict=False)
else:
network_def = ipaddress.ip_network(unicode(prefix), strict=False)
primary_gateways[(name, network_def[1])] = {}
intf_with_secondary.remove(name)
return primary_gateways
def load_namespace_config(asic_name): def load_namespace_config(asic_name):
if not SonicDBConfig.isInit(): if not SonicDBConfig.isInit():
if is_multi_asic(): if is_multi_asic():
@ -247,6 +269,7 @@ def _get_jinja2_env(paths):
env.filters['unique_name'] = unique_name env.filters['unique_name'] = unique_name
env.filters['pfx_filter'] = pfx_filter env.filters['pfx_filter'] = pfx_filter
env.filters['ip_network'] = ip_network env.filters['ip_network'] = ip_network
env.filters['get_primary_addr'] = get_primary_addr
for attr in ['ip', 'network', 'prefixlen', 'netmask', 'broadcast']: for attr in ['ip', 'network', 'prefixlen', 'netmask', 'broadcast']:
env.filters[attr] = partial(prefix_attr, attr) env.filters[attr] = partial(prefix_attr, attr)