Skip to content

Commit bef5477

Browse files
authored
[dhcp_relay] Enhance DHCP monitor application to support DHCPv6 (sonic-net#8060)
#### Why I did it Enhance DHCP monitor application following the implementation PR: sonic-net#7772 #### How I did it Add the support for monitoring DHCPv6 packets. #### How to verify it Install an image with this PR and the implementation PR.
1 parent 5e435e0 commit bef5477

File tree

7 files changed

+674
-183
lines changed

7 files changed

+674
-183
lines changed

src/dhcpmon/src/dhcp_device.c

+434-130
Large diffs are not rendered by default.

src/dhcpmon/src/dhcp_device.h

+88-24
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,43 @@
1818

1919

2020
/**
21-
* DHCP message types
21+
* DHCPv4 message types
2222
**/
2323
typedef enum
2424
{
25-
DHCP_MESSAGE_TYPE_DISCOVER = 1,
26-
DHCP_MESSAGE_TYPE_OFFER = 2,
27-
DHCP_MESSAGE_TYPE_REQUEST = 3,
28-
DHCP_MESSAGE_TYPE_DECLINE = 4,
29-
DHCP_MESSAGE_TYPE_ACK = 5,
30-
DHCP_MESSAGE_TYPE_NAK = 6,
31-
DHCP_MESSAGE_TYPE_RELEASE = 7,
32-
DHCP_MESSAGE_TYPE_INFORM = 8,
33-
34-
DHCP_MESSAGE_TYPE_COUNT
35-
} dhcp_message_type_t;
25+
DHCPv4_MESSAGE_TYPE_DISCOVER = 1,
26+
DHCPv4_MESSAGE_TYPE_OFFER = 2,
27+
DHCPv4_MESSAGE_TYPE_REQUEST = 3,
28+
DHCPv4_MESSAGE_TYPE_DECLINE = 4,
29+
DHCPv4_MESSAGE_TYPE_ACK = 5,
30+
DHCPv4_MESSAGE_TYPE_NAK = 6,
31+
DHCPv4_MESSAGE_TYPE_RELEASE = 7,
32+
DHCPv4_MESSAGE_TYPE_INFORM = 8,
33+
34+
DHCPv4_MESSAGE_TYPE_COUNT
35+
} dhcpv4_message_type_t;
36+
37+
/**
38+
* DHCPv6 message types
39+
**/
40+
typedef enum
41+
{
42+
DHCPv6_MESSAGE_TYPE_SOLICIT = 1,
43+
DHCPv6_MESSAGE_TYPE_ADVERTISE = 2,
44+
DHCPv6_MESSAGE_TYPE_REQUEST = 3,
45+
DHCPv6_MESSAGE_TYPE_CONFIRM = 4,
46+
DHCPv6_MESSAGE_TYPE_RENEW = 5,
47+
DHCPv6_MESSAGE_TYPE_REBIND = 6,
48+
DHCPv6_MESSAGE_TYPE_REPLY = 7,
49+
DHCPv6_MESSAGE_TYPE_RELEASE = 8,
50+
DHCPv6_MESSAGE_TYPE_DECLINE = 9,
51+
DHCPv6_MESSAGE_TYPE_RECONFIGURE = 10,
52+
DHCPv6_MESSAGE_TYPE_INFORMATION_REQUEST = 11,
53+
DHCPv6_MESSAGE_TYPE_RELAY_FORWARD = 12,
54+
DHCPv6_MESSAGE_TYPE_RELAY_REPLY = 13,
55+
56+
DHCPv6_MESSAGE_TYPE_COUNT
57+
} dhcpv6_message_type_t;
3658

3759
/** packet direction */
3860
typedef enum
@@ -60,26 +82,42 @@ typedef enum
6082
DHCP_MON_STATUS_INDETERMINATE, /** DHCP relay health could not be determined */
6183
} dhcp_mon_status_t;
6284

85+
/** dhcp type */
86+
typedef enum
87+
{
88+
DHCPv4_TYPE,
89+
DHCPv6_TYPE,
90+
} dhcp_type_t;
91+
6392
/** dhcp check type */
6493
typedef enum
6594
{
6695
DHCP_MON_CHECK_NEGATIVE, /** Presence of relayed DHCP packets activity is flagged as unhealthy state */
6796
DHCP_MON_CHECK_POSITIVE, /** Validate that received DORA packets are relayed */
6897
} dhcp_mon_check_t;
6998

99+
typedef struct
100+
{
101+
uint64_t v4counters[DHCP_COUNTERS_COUNT][DHCP_DIR_COUNT][DHCPv4_MESSAGE_TYPE_COUNT];
102+
/** current/snapshot counters of DHCPv4 packets */
103+
uint64_t v6counters[DHCP_COUNTERS_COUNT][DHCP_DIR_COUNT][DHCPv6_MESSAGE_TYPE_COUNT];
104+
/** current/snapshot counters of DHCPv6 packets */
105+
} counters_t;
106+
70107
/** DHCP device (interface) context */
71108
typedef struct
72109
{
73110
int sock; /** Raw socket associated with this device/interface */
74-
in_addr_t ip; /** network address of this device (interface) */
111+
in_addr_t ipv4; /** ipv4 network address of this device (interface) */
112+
struct in6_addr ipv6; /** ipv6 network address of this device (interface) */
75113
uint8_t mac[ETHER_ADDR_LEN]; /** hardware address of this device (interface) */
76-
in_addr_t giaddr_ip; /** Gateway IP address */
114+
in_addr_t giaddr_ip; /** Gateway IPv4 address */
115+
struct in6_addr v6_vlan_ip; /** Vlan IPv6 address */
77116
uint8_t is_uplink; /** north interface? */
78117
char intf[IF_NAMESIZE]; /** device (interface) name */
79118
uint8_t *buffer; /** buffer used to read socket data */
80119
size_t snaplen; /** snap length or buffer size */
81-
uint64_t counters[DHCP_COUNTERS_COUNT][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT];
82-
/** current/snapshot counters of DHCP packets */
120+
counters_t counters; /** counters for DHCPv4/6 packets */
83121
} dhcp_device_context_t;
84122

85123
/**
@@ -94,16 +132,28 @@ typedef struct
94132
int initialize_intf_mac_and_ip_addr(dhcp_device_context_t *context);
95133

96134
/**
97-
* @code dhcp_device_get_ip(context, ip);
135+
* @code dhcp_device_get_ipv4(context, ip);
136+
*
137+
* @brief Accessor method
138+
*
139+
* @param context pointer to device (interface) context
140+
* @param ip(out) pointer to device IPv4
141+
*
142+
* @return 0 on success, otherwise for failure
143+
*/
144+
int dhcp_device_get_ipv4(dhcp_device_context_t *context, in_addr_t *ip);
145+
146+
/**
147+
* @code dhcp_device_get_ipv6(context, ip);
98148
*
99149
* @brief Accessor method
100150
*
101151
* @param context pointer to device (interface) context
102-
* @param ip(out) pointer to device IP
152+
* @param ip(out) pointer to device IPv6
103153
*
104154
* @return 0 on success, otherwise for failure
105155
*/
106-
int dhcp_device_get_ip(dhcp_device_context_t *context, in_addr_t *ip);
156+
int dhcp_device_get_ipv6(dhcp_device_context_t *context, struct in6_addr *ip);
107157

108158
/**
109159
* @code dhcp_device_get_aggregate_context();
@@ -130,21 +180,23 @@ int dhcp_device_init(dhcp_device_context_t **context,
130180
uint8_t is_uplink);
131181

132182
/**
133-
* @code dhcp_device_start_capture(context, snaplen, base, giaddr_ip);
183+
* @code dhcp_device_start_capture(context, snaplen, base, giaddr_ip, v6_vlan_ip);
134184
*
135185
* @brief starts packet capture on this interface
136186
*
137187
* @param context pointer to device (interface) context
138188
* @param snaplen length of packet capture
139189
* @param base pointer to libevent base
140190
* @param giaddr_ip gateway IP address
191+
* @param v6_vlan_ip vlan IPv6 address
141192
*
142193
* @return 0 on success, otherwise for failure
143194
*/
144195
int dhcp_device_start_capture(dhcp_device_context_t *context,
145196
size_t snaplen,
146197
struct event_base *base,
147-
in_addr_t giaddr_ip);
198+
in_addr_t giaddr_ip,
199+
struct in6_addr v6_vlan_ip);
148200

149201
/**
150202
* @code dhcp_device_shutdown(context);
@@ -158,17 +210,18 @@ int dhcp_device_start_capture(dhcp_device_context_t *context,
158210
void dhcp_device_shutdown(dhcp_device_context_t *context);
159211

160212
/**
161-
* @code dhcp_device_get_status(check_type, context);
213+
* @code dhcp_device_get_status(check_type, context, type);
162214
*
163215
* @brief collects DHCP relay status info for a given interface. If context is null, it will report aggregate
164216
* status
165217
*
166218
* @param check_type Type of validation
167219
* @param context Device (interface) context
220+
* @param type DHCP type
168221
*
169222
* @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE
170223
*/
171-
dhcp_mon_status_t dhcp_device_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context);
224+
dhcp_mon_status_t dhcp_device_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context, dhcp_type_t type);
172225

173226
/**
174227
* @code dhcp_device_update_snapshot(context);
@@ -185,10 +238,21 @@ void dhcp_device_update_snapshot(dhcp_device_context_t *context);
185238
* @brief prints status counters to syslog. If context is null, it will print aggregate status
186239
*
187240
* @param context Device (interface) context
188-
* @param counters_type Counter type to be printed
241+
* @param type Counter type to be printed
189242
*
190243
* @return none
191244
*/
192245
void dhcp_device_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type);
193246

247+
/**
248+
* @code dhcp_device_active_types(dhcpv4, dhcpv6);
249+
*
250+
* @brief update local variables with active protocols
251+
*
252+
* @param dhcpv4 DHCPv4 enable flag
253+
* @param dhcpv6 DHCPv6 enable flag
254+
*
255+
* @return none
256+
*/
257+
void dhcp_device_active_types(bool dhcpv4, bool dhcpv6);
194258
#endif /* DHCP_DEVICE_H_ */

src/dhcpmon/src/dhcp_devman.c

+25-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <syslog.h>
1010
#include <sys/queue.h>
1111
#include <stdlib.h>
12+
#include <arpa/inet.h>
13+
#include <stdbool.h>
1214

1315
#include "dhcp_devman.h"
1416

@@ -35,7 +37,8 @@ static uint32_t dhcp_num_mgmt_intf = 0;
3537

3638
/** On Device vlan interface IP address corresponding vlan downlink IP
3739
* This IP is used to filter Offer/Ack packet coming from DHCP server */
38-
static in_addr_t vlan_ip = 0;
40+
static in_addr_t v4_vlan_ip = 0;
41+
static struct in6_addr v6_vlan_ip = {0};
3942

4043
/* Device loopback interface ip, which will be used as the giaddr in dual tor setup. */
4144
static in_addr_t loopback_ip = 0;
@@ -136,7 +139,8 @@ int dhcp_devman_add_intf(const char *name, char intf_type)
136139

137140
rv = dhcp_device_init(&dev->dev_context, dev->name, dev->is_uplink);
138141
if (rv == 0 && intf_type == 'd') {
139-
rv = dhcp_device_get_ip(dev->dev_context, &vlan_ip);
142+
rv = dhcp_device_get_ipv4(dev->dev_context, &v4_vlan_ip);
143+
rv = dhcp_device_get_ipv6(dev->dev_context, &v6_vlan_ip);
140144

141145
dhcp_device_context_t *agg_dev = dhcp_device_get_aggregate_context();
142146

@@ -174,7 +178,7 @@ int dhcp_devman_setup_dual_tor_mode(const char *name)
174178
}
175179

176180
if (initialize_intf_mac_and_ip_addr(&loopback_intf_context) == 0 &&
177-
dhcp_device_get_ip(&loopback_intf_context, &loopback_ip) == 0) {
181+
dhcp_device_get_ipv4(&loopback_intf_context, &loopback_ip) == 0) {
178182
dual_tor_mode = 1;
179183
} else {
180184
syslog(LOG_ALERT, "failed to retrieve ip addr for loopback interface (%s)", name);
@@ -197,11 +201,13 @@ int dhcp_devman_start_capture(size_t snaplen, struct event_base *base)
197201

198202
if ((dhcp_num_south_intf == 1) && (dhcp_num_north_intf >= 1)) {
199203
LIST_FOREACH(int_ptr, &intfs, entry) {
200-
rv = dhcp_device_start_capture(int_ptr->dev_context, snaplen, base, dual_tor_mode ? loopback_ip : vlan_ip);
204+
rv = dhcp_device_start_capture(int_ptr->dev_context, snaplen, base, dual_tor_mode ? loopback_ip : v4_vlan_ip, v6_vlan_ip);
201205
if (rv == 0) {
206+
char ipv6_addr[INET6_ADDRSTRLEN];
207+
inet_ntop(AF_INET6, &int_ptr->dev_context->ipv6, ipv6_addr, sizeof(ipv6_addr));
202208
syslog(LOG_INFO,
203-
"Capturing DHCP packets on interface %s, ip: 0x%08x, mac [%02x:%02x:%02x:%02x:%02x:%02x] \n",
204-
int_ptr->name, int_ptr->dev_context->ip, int_ptr->dev_context->mac[0],
209+
"Capturing DHCP packets on interface %s, ipv4: 0x%08x, ipv6: %s, mac [%02x:%02x:%02x:%02x:%02x:%02x] \n",
210+
int_ptr->name, int_ptr->dev_context->ipv4, ipv6_addr, int_ptr->dev_context->mac[0],
205211
int_ptr->dev_context->mac[1], int_ptr->dev_context->mac[2], int_ptr->dev_context->mac[3],
206212
int_ptr->dev_context->mac[4], int_ptr->dev_context->mac[5]);
207213
}
@@ -219,13 +225,13 @@ int dhcp_devman_start_capture(size_t snaplen, struct event_base *base)
219225
}
220226

221227
/**
222-
* @code dhcp_devman_get_status(check_type, context);
228+
* @code dhcp_devman_get_status(check_type, context, type);
223229
*
224230
* @brief collects DHCP relay status info.
225231
*/
226-
dhcp_mon_status_t dhcp_devman_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context)
232+
dhcp_mon_status_t dhcp_devman_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context, dhcp_type_t type)
227233
{
228-
return dhcp_device_get_status(check_type, context);
234+
return dhcp_device_get_status(check_type, context, type);
229235
}
230236

231237
/**
@@ -267,3 +273,13 @@ void dhcp_devman_print_status(dhcp_device_context_t *context, dhcp_counters_type
267273
dhcp_device_print_status(context, type);
268274
}
269275
}
276+
277+
/**
278+
* @code dhcp_devman_active_types(dhcpv4, dhcpv6);
279+
*
280+
* @brief update local variables with active protocols
281+
*/
282+
void dhcp_devman_active_types(bool dhcpv4, bool dhcpv6)
283+
{
284+
dhcp_device_active_types(dhcpv4, dhcpv6);
285+
}

src/dhcpmon/src/dhcp_devman.h

+15-2
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,17 @@ int dhcp_devman_setup_dual_tor_mode(const char *name);
8787
int dhcp_devman_start_capture(size_t snaplen, struct event_base *base);
8888

8989
/**
90-
* @code dhcp_devman_get_status(check_type, context);
90+
* @code dhcp_devman_get_status(check_type, context, type);
9191
*
9292
* @brief collects DHCP relay status info.
9393
*
9494
* @param check_type Type of validation
9595
* @param context pointer to device (interface) context
96+
* @param type DHCP type
9697
*
9798
* @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE
9899
*/
99-
dhcp_mon_status_t dhcp_devman_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context);
100+
dhcp_mon_status_t dhcp_devman_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context, dhcp_type_t type);
100101

101102
/**
102103
* @code dhcp_devman_update_snapshot(context);
@@ -119,4 +120,16 @@ void dhcp_devman_update_snapshot(dhcp_device_context_t *context);
119120
*/
120121
void dhcp_devman_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type);
121122

123+
/**
124+
* @code dhcp_devman_active_types(dhcpv4, dhcpv6);
125+
*
126+
* @brief update local variables with active protocols
127+
*
128+
* @param dhcpv4 flag indicating dhcpv4 is enabled
129+
* @param dhcpv6 flag indicating dhcpv6 is enabled
130+
*
131+
* @return none
132+
*/
133+
void dhcp_devman_active_types(bool dhcpv4, bool dhcpv6);
134+
122135
#endif /* DHCP_DEVMAN_H_ */

0 commit comments

Comments
 (0)