Skip to content

Commit bc69f6d

Browse files
committed
Add support for ipv6
1 parent 5636443 commit bc69f6d

22 files changed

+4209
-2070
lines changed

.azure-pipelines/build.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ jobs:
4242
libnl-genl-3-dev \
4343
libnl-nf-3-dev \
4444
libevent-dev \
45-
libjsoncpp-dev
45+
libjsoncpp-dev \
46+
libpcap-dev
4647
displayName: "Install dependencies"
4748
- checkout: self
4849
clean: true

objects.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
USER_OBJS :=
22

3-
LIBS := -levent -lexplain -lswsscommon -ljsoncpp -pthread -lboost_thread -lboost_system -lhiredis -levent -levent_pthreads -lpthread
3+
LIBS := -levent -lexplain -lswsscommon -ljsoncpp -pthread -lboost_thread -lboost_system -lhiredis -levent -levent_pthreads -lpthread -lpcap
44

src/dhcp_device.cpp

Lines changed: 343 additions & 1107 deletions
Large diffs are not rendered by default.

src/dhcp_device.h

Lines changed: 115 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
/**
22
* @file dhcp_device.h
33
*
4-
* device (interface) module
4+
* device (interface) module
5+
*
6+
* Collection of functions to manage context interface information, it's creation, deletion, and various checks on an interface.
7+
* Context interface is the interface input directly from command line. However operations on specific context interface has been
8+
* extended to physical interfaces under the context interface, as well as aggregate interfaces. Thus we don't use context interface
9+
* directly in many places, instead we use interface name string to identify an interface. In case we need context interface info, we
10+
* will query device manager to get the context interface from interface name.
511
*/
612

713
#ifndef DHCP_DEVICE_H_
@@ -11,52 +17,53 @@
1117
#include <net/if.h>
1218
#include <netinet/in.h>
1319
#include <net/ethernet.h>
14-
15-
#include <event2/listener.h>
16-
#include <event2/bufferevent.h>
17-
#include <event2/buffer.h>
18-
#include <event2/thread.h>
19-
20-
#include "subscriberstatetable.h"
21-
#include "util.h"
22-
23-
extern std::shared_ptr<swss::DBConnector> mCountersDbPtr;
24-
extern std::shared_ptr<swss::DBConnector> mStateDbPtr;
25-
extern bool dual_tor_sock;
26-
extern std::unordered_map<std::string, struct intf*> intfs;
20+
#include <string>
2721

2822
/**
2923
* DHCP message types
3024
**/
3125
typedef enum
3226
{
33-
DHCP_MESSAGE_TYPE_DISCOVER = 1,
34-
DHCP_MESSAGE_TYPE_OFFER = 2,
35-
DHCP_MESSAGE_TYPE_REQUEST = 3,
36-
DHCP_MESSAGE_TYPE_DECLINE = 4,
37-
DHCP_MESSAGE_TYPE_ACK = 5,
38-
DHCP_MESSAGE_TYPE_NAK = 6,
39-
DHCP_MESSAGE_TYPE_RELEASE = 7,
40-
DHCP_MESSAGE_TYPE_INFORM = 8,
41-
BOOTP_MESSAGE = 9,
42-
MALFORMED = 10,
43-
27+
DHCP_MESSAGE_TYPE_UNKNOWN,
28+
DHCP_MESSAGE_TYPE_DISCOVER,
29+
DHCP_MESSAGE_TYPE_OFFER,
30+
DHCP_MESSAGE_TYPE_REQUEST,
31+
DHCP_MESSAGE_TYPE_DECLINE,
32+
DHCP_MESSAGE_TYPE_ACK,
33+
DHCP_MESSAGE_TYPE_NAK,
34+
DHCP_MESSAGE_TYPE_RELEASE,
35+
DHCP_MESSAGE_TYPE_INFORM, // last of standard types
36+
DHCP_MESSAGE_TYPE_BOOTP,
37+
DHCP_MESSAGE_TYPE_MALFORMED,
38+
DHCP_MESSAGE_TYPE_DROPPED,
4439
DHCP_MESSAGE_TYPE_COUNT
4540
} dhcp_message_type_t;
4641

47-
enum
48-
{
49-
OPTION_DHCP_MESSAGE_TYPE = 53,
50-
};
42+
/* db counter name array, message type range [1, 9] */
43+
extern const std::string db_counter_name[DHCP_MESSAGE_TYPE_COUNT];
5144

52-
/** counters type */
5345
typedef enum
5446
{
55-
DHCP_COUNTERS_CURRENT, /** DHCP current counters */
56-
DHCP_COUNTERS_SNAPSHOT, /** DHCP snapshot counters */
57-
58-
DHCP_COUNTERS_COUNT
59-
} dhcp_counters_type_t;
47+
DHCPV6_MESSAGE_TYPE_UNKNOWN,
48+
DHCPV6_MESSAGE_TYPE_SOLICIT,
49+
DHCPV6_MESSAGE_TYPE_ADVERTISE,
50+
DHCPV6_MESSAGE_TYPE_REQUEST,
51+
DHCPV6_MESSAGE_TYPE_CONFIRM,
52+
DHCPV6_MESSAGE_TYPE_RENEW,
53+
DHCPV6_MESSAGE_TYPE_REBIND,
54+
DHCPV6_MESSAGE_TYPE_REPLY,
55+
DHCPV6_MESSAGE_TYPE_RELEASE,
56+
DHCPV6_MESSAGE_TYPE_DECLINE,
57+
DHCPV6_MESSAGE_TYPE_RECONFIGURE,
58+
DHCPV6_MESSAGE_TYPE_INFORMATION_REQUEST,
59+
DHCPV6_MESSAGE_TYPE_RELAY_FORW,
60+
DHCPV6_MESSAGE_TYPE_RELAY_REPL, // last of standard types
61+
DHCPV6_MESSAGE_TYPE_MALFORMED,
62+
DHCPV6_MESSAGE_TYPE_DROPPED,
63+
DHCPV6_MESSAGE_TYPE_COUNT
64+
} dhcpv6_message_type_t;
65+
66+
extern const std::string db_counter_name_v6[DHCPV6_MESSAGE_TYPE_COUNT];
6067

6168
/** dhcp health status */
6269
typedef enum
@@ -66,182 +73,140 @@ typedef enum
6673
DHCP_MON_STATUS_INDETERMINATE, /** DHCP relay health could not be determined */
6774
} dhcp_mon_status_t;
6875

69-
/** dhcp check type */
76+
/** counters type */
7077
typedef enum
7178
{
72-
DHCP_MON_CHECK_NEGATIVE, /** Presence of relayed DHCP packets activity is flagged as unhealthy state */
73-
DHCP_MON_CHECK_POSITIVE, /** Validate that received DORA packets are relayed */
74-
} dhcp_mon_check_t;
79+
DHCP_COUNTERS_CURRENT,
80+
DHCP_COUNTERS_SNAPSHOT,
81+
DHCP_COUNTERS_CURRENT_V6,
82+
DHCP_COUNTERS_SNAPSHOT_V6,
83+
DHCP_COUNTERS_COUNT
84+
} dhcp_counters_type_t;
7585

86+
/** dhcp check type */
7687
typedef enum
7788
{
78-
DHCP_VALID,
79-
DHCP_INVALID,
80-
DHCP_UNKNOWN
81-
} dhcp_mon_packet_valid_type_t;
89+
DHCP_MON_CHECK_NEGATIVE, /** Presence of relayed DHCP packets activity is flagged as unhealthy state */
90+
DHCP_MON_CHECK_POSITIVE, /** Validate that received DORA packets are relayed */
91+
DHCP_MON_CHECK_NEGATIVE_V6, /** Presence of relayed DHCPv6 packets activity is flagged as unhealthy state */
92+
DHCP_MON_CHECK_POSITIVE_V6, /** Validate that received SARR packets are relayed */
93+
DHCP_MON_CHECK_AGG_EQUAL_RX, /** Validate that aggregate device rx counters equal sum of member interfaces rx counters */
94+
DHCP_MON_CHECK_AGG_EQUAL_TX, /** Validate that aggregate device tx counters equal sum of member interfaces tx counters */
95+
DHCP_MON_CHECK_AGG_EQUAL_RX_V6, /** Validate that aggregate device rx counters equal sum of member interfaces rx counters for IPv6 */
96+
DHCP_MON_CHECK_AGG_EQUAL_TX_V6, /** Validate that aggregate device tx counters equal sum of member interfaces tx counters for IPv6 */
97+
DHCP_MON_CHECK_AGG_MULTIPLE_RX, /** Validate that aggregate device rx counters are multiple of member interfaces rx counters */
98+
DHCP_MON_CHECK_AGG_MULTIPLE_TX, /** Validate that aggregate device tx counters are multiple of member interfaces tx counters */
99+
DHCP_MON_CHECK_AGG_MULTIPLE_RX_V6, /** Validate that aggregate device rx counters are multiple of member interfaces rx counters for IPv6 */
100+
DHCP_MON_CHECK_AGG_MULTIPLE_TX_V6 /** Validate that aggregate device tx counters are multiple of member interfaces tx counters for IPv6 */
101+
} dhcp_mon_check_t;
102+
103+
/** Monitored DHCP message type */
104+
extern const dhcp_message_type_t monitored_msgs[];
105+
106+
/** Number of monitored DHCP message type */
107+
extern uint8_t monitored_msg_sz;
108+
109+
/** Monitored DHCPv6 message type */
110+
extern const dhcpv6_message_type_t monitored_v6_msgs[];
111+
112+
/** Number of monitored DHCPv6 message type */
113+
extern uint8_t monitored_v6_msg_sz;
82114

83115
/** DHCP device (interface) context */
84116
typedef struct
85117
{
86-
int rx_sock; /** Raw socket associated with this device/interface to count rx packets */
87-
int tx_sock; /** Raw socket associated with this device/interface to count tx packets*/
88-
in_addr_t ip; /** network address of this device (interface) */
89-
uint8_t mac[ETHER_ADDR_LEN]; /** hardware address of this device (interface) */
90-
in_addr_t giaddr_ip; /** Gateway IP address */
91-
uint8_t is_uplink; /** north interface? */
92-
char intf[IF_NAMESIZE]; /** device (interface) name */
93-
size_t snaplen; /** snap length or buffer size */
94-
uint64_t counters[DHCP_COUNTERS_COUNT][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT];
95-
/** current/snapshot counters of DHCP packets */
118+
uint8_t mac[ETHER_ADDR_LEN]; /** hardware address of this device (interface) */
119+
bool is_uplink; /** north interface? */
120+
bool is_downlink; /** south interface? */
121+
char intf[IF_NAMESIZE]; /** device (interface) name */
122+
struct in_addr ip; /** network address of this device (interface) */
123+
struct in6_addr ipv6_gua; /** network address of this device (interface) */
124+
struct in6_addr ipv6_lla; /** link local address of this device (interface) */
96125
} dhcp_device_context_t;
97126

98-
extern std::string db_counter_name[DHCP_MESSAGE_TYPE_COUNT];
99-
100127
/**
101128
* @code initialize_intf_mac_and_ip_addr(context);
102129
*
103130
* @brief initializes device (interface) mac/ip addresses
104131
*
105132
* @param context pointer to device (interface) context
106133
*
107-
* @return 0 on success, otherwise for failure
134+
* @return 0 on success, negative for failure
108135
*/
109136
int initialize_intf_mac_and_ip_addr(dhcp_device_context_t *context);
110137

111138
/**
112139
* @code dhcp_device_get_ip(context, ip);
113140
*
114-
* @brief Accessor method
141+
* @brief Accessor method, retrieves device (interface) IP address from context and store it in ip if ip is not NULL
115142
*
116143
* @param context pointer to device (interface) context
117144
* @param ip(out) pointer to device IP
145+
* @param ipv6_gua(out) pointer to device IPv6 GUA
146+
* @param ipv6_lla(out) pointer to device IPv6 LLA
118147
*
119-
* @return 0 on success, otherwise for failure
120-
*/
121-
int dhcp_device_get_ip(dhcp_device_context_t *context, in_addr_t *ip);
122-
123-
/**
124-
* @code dhcp_device_get_aggregate_context();
125-
*
126-
* @brief Accessor method
127-
*
128-
* @return pointer to aggregate device (interface) context
129-
*/
130-
dhcp_device_context_t* dhcp_device_get_aggregate_context();
131-
132-
/**
133-
* @code dhcp_device_get_counter(dhcp_packet_direction_t dir);
134-
* @brief Accessor method
135-
* @return pointer to counter
148+
* @return none
136149
*/
137-
std::unordered_map<std::string, std::unordered_map<uint8_t, uint64_t>>* dhcp_device_get_counter(dhcp_packet_direction_t dir);
150+
void dhcp_device_get_ip(const dhcp_device_context_t *context, in_addr *ip, in6_addr *ipv6_gua, in6_addr *ipv6_lla);
138151

139152
/**
140-
* @code dhcp_device_init(context, intf, is_uplink);
153+
* @code dhcp_device_init(ifname, is_uplink);
141154
*
142155
* @brief initializes device (interface) that handles packet capture per interface.
143156
*
144-
* @param context(inout) pointer to device (interface) context
145-
* @param intf interface name
146-
* @param is_uplink uplink interface
147-
*
148-
* @return 0 on success, otherwise for failure
149-
*/
150-
int dhcp_device_init(dhcp_device_context_t **context,
151-
const char *intf,
152-
uint8_t is_uplink);
153-
154-
/**
155-
* @code int dhcp_device_start_capture(size_t snaplen, struct event_mgr *rx_event_mgr, struct event_mgr *tx_event_mgr, in_addr_t giaddr_ip);
156-
*
157-
* @brief starts packet capture on this interface
158-
*
159-
* @param snaplen length of packet capture
160-
* @param rx_event_mgr evnet mgr for rx event
161-
* @param tx_event_mgr event mgr for for tx event
162-
* @param giaddr_ip gateway IP address
157+
* @param ifname interface name
158+
* @param intf_type 'u' for uplink (north) interface, 'd' for downlink (south) interface, 'm' for mgmt interface
163159
*
164-
* @return 0 on success, otherwise for failure
160+
* @return pointer to device (interface) context on success, NULL otherwise
165161
*/
166-
int dhcp_device_start_capture(size_t snaplen, struct event_mgr *rx_event_mgr, struct event_mgr *tx_event_mgr, in_addr_t giaddr_ip);
162+
dhcp_device_context_t* dhcp_device_init(const char *ifname, char intf_type);
167163

168164
/**
169-
* @code dhcp_device_shutdown(context);
165+
* @code dhcp_device_free(context);
170166
*
171-
* @brief shuts down device (interface). Also, stops packet capture on interface and cleans up any allocated memory
167+
* @brief frees device (interface) context
172168
*
173-
* @param context Device (interface) context
169+
* @param context pointer to device (interface) context
174170
*
175-
* @return nonedhcp_device_shutdown
171+
* @return none
176172
*/
177-
void dhcp_device_shutdown(dhcp_device_context_t *context);
173+
void dhcp_device_free(dhcp_device_context_t *context);
178174

179175
/**
180-
* @code dhcp_device_get_status(check_type, context);
176+
* @code dhcp_device_get_status(ifname, check_type);
181177
*
182-
* @brief collects DHCP relay status info for a given interface. If context is null, it will report aggregate
183-
* status
178+
* @brief collects DHCPv4/v6 relay status info for a given interface. The interface name can be context interface name,
179+
* physical interface name under context interface, or aggregate interface name.
184180
*
181+
* @param ifname Interface name
185182
* @param check_type Type of validation
186-
* @param context Device (interface) context
187183
*
188184
* @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE
189185
*/
190-
dhcp_mon_status_t dhcp_device_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context);
186+
dhcp_mon_status_t dhcp_device_get_status(const std::string &ifname, dhcp_mon_check_t check_type);
191187

192188
/**
193-
* @code dhcp_device_update_snapshot(context);
189+
* @code dhcp_device_print_status(ifname, type);
190+
*
191+
* @brief prints status counters to syslog.
194192
*
195-
* @param context Device (interface) context
193+
* @param ifname interface name
194+
* @param type counter type
196195
*
197-
* @brief Update device/interface counters snapshot
196+
* @return none
198197
*/
199-
void dhcp_device_update_snapshot(dhcp_device_context_t *context);
198+
void dhcp_device_print_status(const std::string &ifname, dhcp_counters_type_t type);
200199

201200
/**
202-
* @code dhcp_device_print_status(context, type);
201+
* @code dhcp_device_print_status_debug(ifname, type);
203202
*
204-
* @brief prints status counters to syslog. If context is null, it will print aggregate status
203+
* @brief prints status counters to syslog when debug_on is true.
205204
*
206-
* @param context Device (interface) context
207-
* @param counters_type Counter type to be printed
205+
* @param ifname interface name
206+
* @param type counter type
208207
*
209208
* @return none
210209
*/
211-
void dhcp_device_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type);
212-
213-
/**
214-
* @code void initialize_db_counter(const std::string &ifname)
215-
* @brief Initialize the counter in counters_db with interface name
216-
* @param ifname interface name
217-
* @return none
218-
*/
219-
void initialize_db_counters(const std::string &ifname);
220-
221-
/**
222-
* @code initialize_cache_counter(std::unordered_map<std::string, std::unordered_map<uint8_t, uint64_t>> &counters, std::string interface_name);
223-
* @brief Initialize cache counter per interface
224-
* @param counters counter data
225-
* @param interface_name string value of interface name
226-
*/
227-
void initialize_cache_counter(std::unordered_map<std::string, std::unordered_map<uint8_t, uint64_t>> &counters, std::string interface_name);
228-
229-
/**
230-
* @code void increase_cache_counter(std::string &ifname, uint8_t type, dhcp_packet_direction_t dir)
231-
* @brief Increase cache counter
232-
* @param ifname Interface name
233-
* @param type Packet type
234-
* @param dir Packet direction
235-
* @return none
236-
*/
237-
void increase_cache_counter(std::string &ifname, uint8_t type, dhcp_packet_direction_t dir);
238-
239-
/**
240-
* @code std::string generate_json_string(const std::unordered_map<uint8_t, uint64_t>* counter)
241-
* @brief Generate JSON string by counter dict
242-
* @param counter Counter dict
243-
* @return none
244-
*/
245-
std::string generate_json_string(const std::unordered_map<uint8_t, uint64_t>* counter);
210+
void dhcp_device_print_status_debug(const std::string &ifname, dhcp_counters_type_t type);
246211

247212
#endif /* DHCP_DEVICE_H_ */

0 commit comments

Comments
 (0)