dhcpmon: support dual tor scenario (#7471)

This commit is contained in:
trzhang-msft 2021-05-03 10:51:26 -07:00 committed by Danny Allen
parent d76206bae4
commit 1c2c1f50ba
5 changed files with 79 additions and 13 deletions

View File

@ -130,7 +130,7 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context,
case DHCP_MESSAGE_TYPE_INFORM: case DHCP_MESSAGE_TYPE_INFORM:
giaddr = ntohl(dhcphdr[DHCP_GIADDR_OFFSET] << 24 | dhcphdr[DHCP_GIADDR_OFFSET + 1] << 16 | giaddr = ntohl(dhcphdr[DHCP_GIADDR_OFFSET] << 24 | dhcphdr[DHCP_GIADDR_OFFSET + 1] << 16 |
dhcphdr[DHCP_GIADDR_OFFSET + 2] << 8 | dhcphdr[DHCP_GIADDR_OFFSET + 3]); 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->is_uplink && dir == DHCP_RX && iphdr->ip_dst.s_addr == INADDR_BROADCAST)) {
context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
@ -140,7 +140,7 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context,
case DHCP_MESSAGE_TYPE_OFFER: case DHCP_MESSAGE_TYPE_OFFER:
case DHCP_MESSAGE_TYPE_ACK: case DHCP_MESSAGE_TYPE_ACK:
case DHCP_MESSAGE_TYPE_NAK: 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->is_uplink && dir == DHCP_TX)) {
context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
@ -438,7 +438,7 @@ static int init_socket(dhcp_device_context_t *context, const char *intf)
* *
* @return 0 on success, otherwise for failure * @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; int rv = -1;
@ -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 * @brief starts packet capture on this interface
*/ */
int dhcp_device_start_capture(dhcp_device_context_t *context, int dhcp_device_start_capture(dhcp_device_context_t *context,
size_t snaplen, size_t snaplen,
struct event_base *base, struct event_base *base,
in_addr_t vlan_ip) in_addr_t giaddr_ip)
{ {
int rv = -1; int rv = -1;
@ -565,7 +565,7 @@ int dhcp_device_start_capture(dhcp_device_context_t *context,
break; break;
} }
context->vlan_ip = vlan_ip; context->giaddr_ip = giaddr_ip;
context->buffer = (uint8_t *) malloc(snaplen); context->buffer = (uint8_t *) malloc(snaplen);
if (context->buffer == NULL) { if (context->buffer == NULL) {

View File

@ -73,7 +73,7 @@ typedef struct
int sock; /** Raw socket associated with this device/interface */ int sock; /** Raw socket associated with this device/interface */
in_addr_t ip; /** network address of 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) */ 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? */ uint8_t is_uplink; /** north interface? */
char intf[IF_NAMESIZE]; /** device (interface) name */ char intf[IF_NAMESIZE]; /** device (interface) name */
uint8_t *buffer; /** buffer used to read socket data */ uint8_t *buffer; /** buffer used to read socket data */
@ -82,6 +82,17 @@ typedef struct
/** current/snapshot counters of DHCP packets */ /** current/snapshot counters of DHCP packets */
} dhcp_device_context_t; } 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); * @code dhcp_device_get_ip(context, ip);
* *
@ -119,21 +130,21 @@ int dhcp_device_init(dhcp_device_context_t **context,
uint8_t is_uplink); 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 * @brief starts packet capture on this interface
* *
* @param context pointer to device (interface) context * @param context pointer to device (interface) context
* @param snaplen length of packet capture * @param snaplen length of packet capture
* @param base pointer to libevent base * @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 * @return 0 on success, otherwise for failure
*/ */
int dhcp_device_start_capture(dhcp_device_context_t *context, int dhcp_device_start_capture(dhcp_device_context_t *context,
size_t snaplen, size_t snaplen,
struct event_base *base, struct event_base *base,
in_addr_t vlan_ip); in_addr_t giaddr_ip);
/** /**
* @code dhcp_device_shutdown(context); * @code dhcp_device_shutdown(context);

View File

@ -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 */ * This IP is used to filter Offer/Ack packet coming from DHCP server */
static in_addr_t vlan_ip = 0; 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 */ /** mgmt interface */
static struct intf *mgmt_intf = NULL; static struct intf *mgmt_intf = NULL;
@ -148,6 +154,37 @@ int dhcp_devman_add_intf(const char *name, char intf_type)
return rv; 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); * @code dhcp_devman_start_capture(snaplen, base);
* *
@ -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)) { if ((dhcp_num_south_intf == 1) && (dhcp_num_north_intf >= 1)) {
LIST_FOREACH(int_ptr, &intfs, entry) { 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) { if (rv == 0) {
syslog(LOG_INFO, syslog(LOG_INFO,
"Capturing DHCP packets on interface %s, ip: 0x%08x, mac [%02x:%02x:%02x:%02x:%02x:%02x] \n", "Capturing DHCP packets on interface %s, ip: 0x%08x, mac [%02x:%02x:%02x:%02x:%02x:%02x] \n",

View File

@ -63,6 +63,17 @@ dhcp_device_context_t* dhcp_devman_get_mgmt_dev();
*/ */
int dhcp_devman_add_intf(const char *name, char intf_type); 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); * @code dhcp_devman_start_capture(snaplen, base);
* *

View File

@ -40,11 +40,12 @@ static const uint32_t dhcpmon_default_unhealthy_max_count = 10;
*/ */
static void usage(const char *prog) static void usage(const char *prog)
{ {
printf("Usage: %s -id <south interface> {-iu <north interface>}+ -im <mgmt interface> [-w <snapshot window in sec>]" printf("Usage: %s -id <south interface> {-iu <north interface>}+ -im <mgmt interface> [-u <loopback interface>]"
"[-c <unhealthy status count>] [-s <snap length>] [-d]\n", prog); "[-w <snapshot window in sec>] [-c <unhealthy status count>] [-s <snap length>] [-d]\n", prog);
printf("where\n"); printf("where\n");
printf("\tsouth interface: is a vlan interface,\n"); printf("\tsouth interface: is a vlan interface,\n");
printf("\tnorth interface: is a TOR-T1 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", printf("\tsnapshot window: during which DHCP counters are gathered and DHCP status is validated (default %d),\n",
dhcpmon_default_health_check_window); dhcpmon_default_health_check_window);
printf("\tunhealthy status count: count of consecutive unhealthy status before writing an alert to syslog " printf("\tunhealthy status count: count of consecutive unhealthy status before writing an alert to syslog "
@ -132,6 +133,12 @@ int main(int argc, char **argv)
} }
i += 2; i += 2;
break; break;
case 'u':
if (dhcp_devman_setup_dual_tor_mode(argv[i + 1]) != 0) {
usage(basename(argv[0]));
}
i += 2;
break;
case 'd': case 'd':
make_daemon = 1; make_daemon = 1;
i++; i++;