Skip to content

Commit

Permalink
dhcpmon: support dual tor scenario (#7471)
Browse files Browse the repository at this point in the history
  • Loading branch information
trzhang-msft authored May 3, 2021
1 parent fa4e355 commit 76eeb23
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 13 deletions.
12 changes: 6 additions & 6 deletions src/dhcp_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context,
case DHCP_MESSAGE_TYPE_INFORM:
giaddr = ntohl(dhcphdr[DHCP_GIADDR_OFFSET] << 24 | dhcphdr[DHCP_GIADDR_OFFSET + 1] << 16 |
dhcphdr[DHCP_GIADDR_OFFSET + 2] << 8 | dhcphdr[DHCP_GIADDR_OFFSET + 3]);
if ((context->vlan_ip == giaddr && context->is_uplink && dir == DHCP_TX) ||
if ((context->giaddr_ip == giaddr && context->is_uplink && dir == DHCP_TX) ||
(!context->is_uplink && dir == DHCP_RX && iphdr->ip_dst.s_addr == INADDR_BROADCAST)) {
context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
Expand All @@ -140,7 +140,7 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context,
case DHCP_MESSAGE_TYPE_OFFER:
case DHCP_MESSAGE_TYPE_ACK:
case DHCP_MESSAGE_TYPE_NAK:
if ((context->vlan_ip == iphdr->ip_dst.s_addr && context->is_uplink && dir == DHCP_RX) ||
if ((context->giaddr_ip == iphdr->ip_dst.s_addr && context->is_uplink && dir == DHCP_RX) ||
(!context->is_uplink && dir == DHCP_TX)) {
context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
Expand Down Expand Up @@ -438,7 +438,7 @@ static int init_socket(dhcp_device_context_t *context, const char *intf)
*
* @return 0 on success, otherwise for failure
*/
static int initialize_intf_mac_and_ip_addr(dhcp_device_context_t *context)
int initialize_intf_mac_and_ip_addr(dhcp_device_context_t *context)
{
int rv = -1;

Expand Down Expand Up @@ -543,14 +543,14 @@ int dhcp_device_init(dhcp_device_context_t **context, const char *intf, uint8_t
}

/**
* @code dhcp_device_start_capture(context, snaplen, base, vlan_ip);
* @code dhcp_device_start_capture(context, snaplen, base, giaddr_ip);
*
* @brief starts packet capture on this interface
*/
int dhcp_device_start_capture(dhcp_device_context_t *context,
size_t snaplen,
struct event_base *base,
in_addr_t vlan_ip)
in_addr_t giaddr_ip)
{
int rv = -1;

Expand All @@ -565,7 +565,7 @@ int dhcp_device_start_capture(dhcp_device_context_t *context,
break;
}

context->vlan_ip = vlan_ip;
context->giaddr_ip = giaddr_ip;

context->buffer = (uint8_t *) malloc(snaplen);
if (context->buffer == NULL) {
Expand Down
19 changes: 15 additions & 4 deletions src/dhcp_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ typedef struct
int sock; /** Raw socket associated with this device/interface */
in_addr_t ip; /** network address of this device (interface) */
uint8_t mac[ETHER_ADDR_LEN]; /** hardware address of this device (interface) */
in_addr_t vlan_ip; /** Vlan IP address */
in_addr_t giaddr_ip; /** Gateway IP address */
uint8_t is_uplink; /** north interface? */
char intf[IF_NAMESIZE]; /** device (interface) name */
uint8_t *buffer; /** buffer used to read socket data */
Expand All @@ -82,6 +82,17 @@ typedef struct
/** current/snapshot counters of DHCP packets */
} dhcp_device_context_t;

/**
* @code initialize_intf_mac_and_ip_addr(context);
*
* @brief initializes device (interface) mac/ip addresses
*
* @param context pointer to device (interface) context
*
* @return 0 on success, otherwise for failure
*/
int initialize_intf_mac_and_ip_addr(dhcp_device_context_t *context);

/**
* @code dhcp_device_get_ip(context, ip);
*
Expand Down Expand Up @@ -119,21 +130,21 @@ int dhcp_device_init(dhcp_device_context_t **context,
uint8_t is_uplink);

/**
* @code dhcp_device_start_capture(context, snaplen, base, vlan_ip);
* @code dhcp_device_start_capture(context, snaplen, base, giaddr_ip);
*
* @brief starts packet capture on this interface
*
* @param context pointer to device (interface) context
* @param snaplen length of packet capture
* @param base pointer to libevent base
* @param vlan_ip vlan IP address
* @param giaddr_ip gateway IP address
*
* @return 0 on success, otherwise for failure
*/
int dhcp_device_start_capture(dhcp_device_context_t *context,
size_t snaplen,
struct event_base *base,
in_addr_t vlan_ip);
in_addr_t giaddr_ip);

/**
* @code dhcp_device_shutdown(context);
Expand Down
39 changes: 38 additions & 1 deletion src/dhcp_devman.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ static uint32_t dhcp_num_mgmt_intf = 0;
* This IP is used to filter Offer/Ack packet coming from DHCP server */
static in_addr_t vlan_ip = 0;

/* Device loopback interface ip, which will be used as the giaddr in dual tor setup. */
static in_addr_t loopback_ip = 0;

/* Whether the device is in dual tor mode, 0 as default for single tor mode. */
static int dual_tor_mode = 0;

/** mgmt interface */
static struct intf *mgmt_intf = NULL;

Expand Down Expand Up @@ -148,6 +154,37 @@ int dhcp_devman_add_intf(const char *name, char intf_type)
return rv;
}

/**
* @code dhcp_devman_setup_dual_tor_mode(name);
*
* @brief set up dual tor mode: 1) set dual_tor_mode flag and 2) retrieve loopback_ip.
*/
int dhcp_devman_setup_dual_tor_mode(const char *name)
{
int rv = -1;

dhcp_device_context_t loopback_intf_context;

if (strlen(name) < sizeof(loopback_intf_context.intf)) {
strncpy(loopback_intf_context.intf, name, sizeof(loopback_intf_context.intf) - 1);
loopback_intf_context.intf[sizeof(loopback_intf_context.intf) - 1] = '\0';
} else {
syslog(LOG_ALERT, "loopback interface name (%s) is too long", name);
return rv;
}

if (initialize_intf_mac_and_ip_addr(&loopback_intf_context) == 0 &&
dhcp_device_get_ip(&loopback_intf_context, &loopback_ip) == 0) {
dual_tor_mode = 1;
} else {
syslog(LOG_ALERT, "failed to retrieve ip addr for loopback interface (%s)", name);
return rv;
}

rv = 0;
return rv;
}

/**
* @code dhcp_devman_start_capture(snaplen, base);
*
Expand All @@ -160,7 +197,7 @@ int dhcp_devman_start_capture(size_t snaplen, struct event_base *base)

if ((dhcp_num_south_intf == 1) && (dhcp_num_north_intf >= 1)) {
LIST_FOREACH(int_ptr, &intfs, entry) {
rv = dhcp_device_start_capture(int_ptr->dev_context, snaplen, base, vlan_ip);
rv = dhcp_device_start_capture(int_ptr->dev_context, snaplen, base, dual_tor_mode ? loopback_ip : vlan_ip);
if (rv == 0) {
syslog(LOG_INFO,
"Capturing DHCP packets on interface %s, ip: 0x%08x, mac [%02x:%02x:%02x:%02x:%02x:%02x] \n",
Expand Down
11 changes: 11 additions & 0 deletions src/dhcp_devman.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ dhcp_device_context_t* dhcp_devman_get_mgmt_dev();
*/
int dhcp_devman_add_intf(const char *name, char intf_type);

/**
* @code dhcp_devman_setup_dual_tor_mode(name);
*
* @brief set up dual tor mode: 1) set dual_tor_mode flag and 2) retrieve loopback_ip.
*
* @param name interface name
*
* @return 0 on success, nonzero otherwise
*/
int dhcp_devman_setup_dual_tor_mode(const char *name);

/**
* @code dhcp_devman_start_capture(snaplen, base);
*
Expand Down
11 changes: 9 additions & 2 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ static const uint32_t dhcpmon_default_unhealthy_max_count = 10;
*/
static void usage(const char *prog)
{
printf("Usage: %s -id <south interface> {-iu <north interface>}+ -im <mgmt interface> [-w <snapshot window in sec>]"
"[-c <unhealthy status count>] [-s <snap length>] [-d]\n", prog);
printf("Usage: %s -id <south interface> {-iu <north interface>}+ -im <mgmt interface> [-u <loopback interface>]"
"[-w <snapshot window in sec>] [-c <unhealthy status count>] [-s <snap length>] [-d]\n", prog);
printf("where\n");
printf("\tsouth interface: is a vlan interface,\n");
printf("\tnorth interface: is a TOR-T1 interface,\n");
printf("\tloopback interface: is the loopback interface for dual tor setup,\n");
printf("\tsnapshot window: during which DHCP counters are gathered and DHCP status is validated (default %d),\n",
dhcpmon_default_health_check_window);
printf("\tunhealthy status count: count of consecutive unhealthy status before writing an alert to syslog "
Expand Down Expand Up @@ -132,6 +133,12 @@ int main(int argc, char **argv)
}
i += 2;
break;
case 'u':
if (dhcp_devman_setup_dual_tor_mode(argv[i + 1]) != 0) {
usage(basename(argv[0]));
}
i += 2;
break;
case 'd':
make_daemon = 1;
i++;
Expand Down

0 comments on commit 76eeb23

Please sign in to comment.