Skip to content

Commit

Permalink
[dhcp-relay]: Modify dhcp relay to pick primary address (#17012)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
shbalaku-microsoft authored and yxieca committed Dec 4, 2023
1 parent 26ade35 commit c0963db
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 0 deletions.
3 changes: 3 additions & 0 deletions dockers/docker-dhcp-relay/dhcpv4-relay.agents.j2
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% 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'] %}
{%- if dhcp_server | ipv4 %} {{ dhcp_server }}{% endif -%}
{% endfor %}
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
1 change: 1 addition & 0 deletions src/isc-dhcp/patch/series
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
0012-add-option-si-to-support-using-src-intf-ip-in-relay.patch
0013-Fix-dhcrelay-agent-option-buffer-pointer-logic.patch
0014-enable-parallel-build.patch
0015-option-to-set-primary-address-in-interface.patch
23 changes: 23 additions & 0 deletions src/sonic-config-engine/sonic-cfggen
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import netaddr
import os
import sys
import yaml
import ipaddress

from collections import OrderedDict
from config_samples import generate_sample_config, get_available_config
Expand Down Expand Up @@ -137,6 +138,27 @@ def ip_network(value):
return "Invalid ip address %s" % value
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):
if not SonicDBConfig.isInit():
if is_multi_asic():
Expand Down Expand Up @@ -247,6 +269,7 @@ def _get_jinja2_env(paths):
env.filters['unique_name'] = unique_name
env.filters['pfx_filter'] = pfx_filter
env.filters['ip_network'] = ip_network
env.filters['get_primary_addr'] = get_primary_addr
for attr in ['ip', 'network', 'prefixlen', 'netmask', 'broadcast']:
env.filters[attr] = partial(prefix_attr, attr)

Expand Down

0 comments on commit c0963db

Please sign in to comment.