Update dhcpmon rx/tx packet filtering and fix server rx count (#13898)
Why I did it Dhcpmon had incorrect RX count for server side packets. It does not raise any false alarms, but could miss catching server side packet count mismatch between snapshot and current counter. Add debug mode which prints counter to syslog How I did it Due to dualtor inbound filter requirement, there are currently two filters, each for listening to rx / tx packets. Originally, we opened up an rx/tx socket for each interface specified, which causes duplicate socket. Now we initialize the sockets only once. Both sockets are not binded to an interface, and we use vlan to interface mapping to filter packets. For inbound uplinks, we use a portchannel to interface mapping. Previous dhcpmon counter before dual tor change: [ Agg-Vlan1000- Current rx/tx] Discover: 1/ 4, Offer: 1/ 1, Request: 3/ 12, ACK: 1/ 1 [ eth0- Current rx/tx] Discover: 0/ 0, Offer: 0/ 0, Request: 0/ 0, ACK: 0/ 0 [ eth0- Current rx/tx] Discover: 0/ 0, Offer: 0/ 0, Request: 0/ 0, ACK: 0/ 0 [ PortChannel104- Current rx/tx] Discover: 0/ 1, Offer: 0/ 0, Request: 0/ 3, ACK: 0/ 0 [ PortChannel103- Current rx/tx] Discover: 0/ 1, Offer: 0/ 0, Request: 0/ 3, ACK: 0/ 0 [ PortChannel102- Current rx/tx] Discover: 0/ 2, Offer: 1/ 0, Request: 0/ 6, ACK: 1/ 0 [ PortChannel101- Current rx/tx] Discover: 0/ 0, Offer: 0/ 0, Request: 0/ 0, ACK: 0/ 0 [ Vlan1000- Current rx/tx] Discover: 1/ 0, Offer: 0/ 1, Request: 3/ 0, ACK: 0/ 1 [ Agg-Vlan1000- Current rx/tx] Discover: 1/ 4, Offer: 1/ 1, Request: 3/ 12, ACK: 1/ 1 Dhcpmon counter after this PR: [ PortChannel104- Current rx/tx] Discover: 0/ 1, Offer: 0/ 0, Request: 0/ 3, ACK: 0/ 0 [ PortChannel103- Current rx/tx] Discover: 0/ 1, Offer: 0/ 0, Request: 0/ 3, ACK: 0/ 0 [ PortChannel102- Current rx/tx] Discover: 0/ 2, Offer: 1/ 0, Request: 0/ 6, ACK: 1/ 0 [ PortChannel101- Current rx/tx] Discover: 0/ 0, Offer: 0/ 0, Request: 0/ 0, ACK: 0/ 0 [ Vlan1000- Current rx/tx] Discover: 1/ 0, Offer: 0/ 1, Request: 3/ 0, ACK: 0/ 1 [ Agg-Vlan1000- Current rx/tx] Discover: 1/ 4, Offer: 1/ 1, Request: 3/ 12, ACK: 1/ 1 How to verify it Ran dhcp relay test to send all four packets in singles and batches on both single ToR and dual ToR. Counter was as expected.
This commit is contained in:
parent
a78d4c9750
commit
e528408d14
@ -24,6 +24,7 @@
|
|||||||
#include "subscriberstatetable.h"
|
#include "subscriberstatetable.h"
|
||||||
#include "select.h"
|
#include "select.h"
|
||||||
|
|
||||||
|
#include "dhcp_devman.h"
|
||||||
#include "dhcp_device.h"
|
#include "dhcp_device.h"
|
||||||
|
|
||||||
/** Counter print width */
|
/** Counter print width */
|
||||||
@ -61,6 +62,12 @@ std::shared_ptr<swss::Table> mStateDbMuxTablePtr = std::make_shared<swss::Table>
|
|||||||
/* interface to vlan mapping */
|
/* interface to vlan mapping */
|
||||||
std::unordered_map<std::string, std::string> vlan_map;
|
std::unordered_map<std::string, std::string> vlan_map;
|
||||||
|
|
||||||
|
/* interface to port-channel mapping */
|
||||||
|
std::unordered_map<std::string, std::string> portchan_map;
|
||||||
|
|
||||||
|
/* interface to mgmt port mapping */
|
||||||
|
std::unordered_map<std::string, std::string> mgmt_map;
|
||||||
|
|
||||||
/** Berkeley Packet Filter program for "udp and (port 67 or port 68)".
|
/** Berkeley Packet Filter program for "udp and (port 67 or port 68)".
|
||||||
* This program is obtained using the following command tcpdump:
|
* This program is obtained using the following command tcpdump:
|
||||||
* `tcpdump -dd "outbound and udp and (port 67 or port 68)"`
|
* `tcpdump -dd "outbound and udp and (port 67 or port 68)"`
|
||||||
@ -133,6 +140,10 @@ static struct sock_fprog dhcp_inbound_sock_bfp = {
|
|||||||
.len = sizeof(dhcp_inbound_bpf_code) / sizeof(*dhcp_inbound_bpf_code), .filter = dhcp_inbound_bpf_code
|
.len = sizeof(dhcp_inbound_bpf_code) / sizeof(*dhcp_inbound_bpf_code), .filter = dhcp_inbound_bpf_code
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static uint8_t *rx_recv_buffer = NULL;
|
||||||
|
static uint8_t *tx_recv_buffer = NULL;
|
||||||
|
static uint32_t snap_length;
|
||||||
|
|
||||||
/** Aggregate device of DHCP interfaces. It contains aggregate counters from
|
/** Aggregate device of DHCP interfaces. It contains aggregate counters from
|
||||||
all interfaces
|
all interfaces
|
||||||
*/
|
*/
|
||||||
@ -146,17 +157,56 @@ static dhcp_message_type_t monitored_msgs[] = {
|
|||||||
DHCP_MESSAGE_TYPE_ACK
|
DHCP_MESSAGE_TYPE_ACK
|
||||||
};
|
};
|
||||||
|
|
||||||
void update_vlan_mapping(std::string vlan, std::shared_ptr<swss::DBConnector> mConfigDbPtr) {
|
/** update ethernet interface to vlan map
|
||||||
auto match_pattern = std::string("VLAN_MEMBER|") + vlan + std::string("|*");
|
* VLAN_MEMBER|Vlan1000|Ethernet48
|
||||||
auto keys = mConfigDbPtr->keys(match_pattern);
|
*/
|
||||||
|
void update_vlan_mapping(std::shared_ptr<swss::DBConnector> db_conn) {
|
||||||
|
auto match_pattern = std::string("VLAN_MEMBER|*");
|
||||||
|
auto keys = db_conn->keys(match_pattern);
|
||||||
for (auto &itr : keys) {
|
for (auto &itr : keys) {
|
||||||
auto found = itr.find_last_of('|');
|
auto first = itr.find_first_of('|');
|
||||||
auto interface = itr.substr(found + 1);
|
auto second = itr.find_last_of('|');
|
||||||
|
auto vlan = itr.substr(first + 1, second - first - 1);
|
||||||
|
auto interface = itr.substr(second + 1);
|
||||||
vlan_map[interface] = vlan;
|
vlan_map[interface] = vlan;
|
||||||
syslog(LOG_INFO, "add <%s, %s> into interface vlan map\n", interface.c_str(), vlan.c_str());
|
syslog(LOG_INFO, "add <%s, %s> into interface vlan map\n", interface.c_str(), vlan.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** update ethernet interface to port-channel map
|
||||||
|
* PORTCHANNEL_MEMBER|PortChannel101|Ethernet112
|
||||||
|
*/
|
||||||
|
void update_portchannel_mapping(std::shared_ptr<swss::DBConnector> db_conn) {
|
||||||
|
auto match_pattern = std::string("PORTCHANNEL_MEMBER|*");
|
||||||
|
auto keys = db_conn->keys(match_pattern);
|
||||||
|
for (auto &itr : keys) {
|
||||||
|
auto first = itr.find_first_of('|');
|
||||||
|
auto second = itr.find_last_of('|');
|
||||||
|
auto portchannel = itr.substr(first + 1, second - first - 1);
|
||||||
|
auto interface = itr.substr(second + 1);
|
||||||
|
portchan_map[interface] = portchannel;
|
||||||
|
syslog(LOG_INFO, "add <%s, %s> into interface port-channel map\n", interface.c_str(), portchannel.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** update interface to mgmt map
|
||||||
|
*/
|
||||||
|
void update_mgmt_mapping() {
|
||||||
|
auto mgmt = dhcp_devman_get_mgmt_dev();
|
||||||
|
if (mgmt) {
|
||||||
|
auto name = std::string(mgmt->intf);
|
||||||
|
mgmt_map[name] = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dhcp_device_context_t *find_device_context(std::unordered_map<std::string, struct intf*> *intfs, std::string if_name) {
|
||||||
|
auto intf = intfs->find(if_name);
|
||||||
|
if (intf == intfs->end()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return intf->second->dev_context;
|
||||||
|
}
|
||||||
|
|
||||||
/** Number of monitored DHCP message type */
|
/** Number of monitored DHCP message type */
|
||||||
static uint8_t monitored_msg_sz = sizeof(monitored_msgs) / sizeof(*monitored_msgs);
|
static uint8_t monitored_msg_sz = sizeof(monitored_msgs) / sizeof(*monitored_msgs);
|
||||||
|
|
||||||
@ -222,12 +272,12 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context,
|
|||||||
*
|
*
|
||||||
* @return none
|
* @return none
|
||||||
*/
|
*/
|
||||||
static void client_packet_handler(dhcp_device_context_t *context, ssize_t buffer_sz)
|
static void client_packet_handler(dhcp_device_context_t *context, uint8_t *buffer,
|
||||||
|
ssize_t buffer_sz, dhcp_packet_direction_t dir)
|
||||||
{
|
{
|
||||||
struct ether_header *ethhdr = (struct ether_header*) context->buffer;
|
struct ip *iphdr = (struct ip*) (buffer + IP_START_OFFSET);
|
||||||
struct ip *iphdr = (struct ip*) (context->buffer + IP_START_OFFSET);
|
struct udphdr *udp = (struct udphdr*) (buffer + UDP_START_OFFSET);
|
||||||
struct udphdr *udp = (struct udphdr*) (context->buffer + UDP_START_OFFSET);
|
uint8_t *dhcphdr = buffer + DHCP_START_OFFSET;
|
||||||
uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET;
|
|
||||||
int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE;
|
int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE;
|
||||||
|
|
||||||
if (((unsigned)buffer_sz > UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) &&
|
if (((unsigned)buffer_sz > UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) &&
|
||||||
@ -236,14 +286,8 @@ static void client_packet_handler(dhcp_device_context_t *context, ssize_t buffer
|
|||||||
int dhcp_sz = ntohs(udp->len) < buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr) ?
|
int dhcp_sz = ntohs(udp->len) < buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr) ?
|
||||||
ntohs(udp->len) : buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr);
|
ntohs(udp->len) : buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr);
|
||||||
int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE;
|
int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE;
|
||||||
const u_char *dhcp_option = context->buffer + dhcp_option_offset;
|
const u_char *dhcp_option = buffer + dhcp_option_offset;
|
||||||
dhcp_packet_direction_t dir = (ethhdr->ether_shost[0] == context->mac[0] &&
|
|
||||||
ethhdr->ether_shost[1] == context->mac[1] &&
|
|
||||||
ethhdr->ether_shost[2] == context->mac[2] &&
|
|
||||||
ethhdr->ether_shost[3] == context->mac[3] &&
|
|
||||||
ethhdr->ether_shost[4] == context->mac[4] &&
|
|
||||||
ethhdr->ether_shost[5] == context->mac[5]) ?
|
|
||||||
DHCP_TX : DHCP_RX;
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
while ((offset < (dhcp_option_sz + 1)) && dhcp_option[offset] != 255) {
|
while ((offset < (dhcp_option_sz + 1)) && dhcp_option[offset] != 255) {
|
||||||
if (dhcp_option[offset] == OPTION_DHCP_MESSAGE_TYPE) {
|
if (dhcp_option[offset] == OPTION_DHCP_MESSAGE_TYPE) {
|
||||||
@ -260,11 +304,41 @@ static void client_packet_handler(dhcp_device_context_t *context, ssize_t buffer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
syslog(LOG_WARNING, "read_callback(%s): read length (%ld) is too small to capture DHCP options",
|
syslog(LOG_WARNING, "read_callback(%s %s): read length (%ld) is too small to capture DHCP options",
|
||||||
context->intf, buffer_sz);
|
context->intf, dir == DHCP_TX ? "TX" : "RX", buffer_sz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dhcp_device_context_t *interface_to_dev_context(std::unordered_map<std::string, struct intf*> *devices,
|
||||||
|
std::string ifname)
|
||||||
|
{
|
||||||
|
auto vlan = vlan_map.find(ifname);
|
||||||
|
if (vlan != vlan_map.end()) {
|
||||||
|
if (dual_tor_sock) {
|
||||||
|
std::string state;
|
||||||
|
mStateDbMuxTablePtr->hget(ifname, "state", state);
|
||||||
|
if (state == "standby") {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return find_device_context(devices, vlan->second);
|
||||||
|
} else {
|
||||||
|
auto port_channel = portchan_map.find(ifname);
|
||||||
|
if (port_channel != portchan_map.end()) {
|
||||||
|
return find_device_context(devices, port_channel->second);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// mgmt interface check
|
||||||
|
auto mgmt = mgmt_map.find(ifname);
|
||||||
|
if (mgmt != mgmt_map.end()) {
|
||||||
|
return find_device_context(devices, mgmt->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code read_tx_callback(fd, event, arg);
|
* @code read_tx_callback(fd, event, arg);
|
||||||
*
|
*
|
||||||
@ -278,11 +352,24 @@ static void client_packet_handler(dhcp_device_context_t *context, ssize_t buffer
|
|||||||
*/
|
*/
|
||||||
static void read_tx_callback(int fd, short event, void *arg)
|
static void read_tx_callback(int fd, short event, void *arg)
|
||||||
{
|
{
|
||||||
dhcp_device_context_t *context = (dhcp_device_context_t*) arg;
|
auto devices = (std::unordered_map<std::string, struct intf*> *)arg;
|
||||||
ssize_t buffer_sz;
|
ssize_t buffer_sz;
|
||||||
|
struct sockaddr_ll sll;
|
||||||
|
socklen_t slen = sizeof sll;
|
||||||
|
dhcp_device_context_t *context = NULL;
|
||||||
|
|
||||||
while ((buffer_sz = recv(fd, context->buffer, context->snaplen, MSG_DONTWAIT)) > 0) {
|
while ((buffer_sz = recvfrom(fd, tx_recv_buffer, snap_length, MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0)
|
||||||
client_packet_handler(context, buffer_sz);
|
{
|
||||||
|
char interfaceName[IF_NAMESIZE];
|
||||||
|
if (if_indextoname(sll.sll_ifindex, interfaceName) == NULL) {
|
||||||
|
syslog(LOG_WARNING, "invalid output interface index %d\n", sll.sll_ifindex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string intf(interfaceName);
|
||||||
|
context = find_device_context(devices, intf);
|
||||||
|
if (context) {
|
||||||
|
client_packet_handler(context, tx_recv_buffer, buffer_sz, DHCP_TX);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,12 +386,13 @@ static void read_tx_callback(int fd, short event, void *arg)
|
|||||||
*/
|
*/
|
||||||
static void read_rx_callback(int fd, short event, void *arg)
|
static void read_rx_callback(int fd, short event, void *arg)
|
||||||
{
|
{
|
||||||
dhcp_device_context_t *context = (dhcp_device_context_t*) arg;
|
auto devices = (std::unordered_map<std::string, struct intf*> *)arg;
|
||||||
ssize_t buffer_sz;
|
ssize_t buffer_sz;
|
||||||
struct sockaddr_ll sll;
|
struct sockaddr_ll sll;
|
||||||
socklen_t slen = sizeof sll;
|
socklen_t slen = sizeof(sll);
|
||||||
|
dhcp_device_context_t *context = NULL;
|
||||||
|
|
||||||
while ((buffer_sz = recvfrom(fd, context->buffer, context->snaplen, MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0)
|
while ((buffer_sz = recvfrom(fd, rx_recv_buffer, snap_length, MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0)
|
||||||
{
|
{
|
||||||
char interfaceName[IF_NAMESIZE];
|
char interfaceName[IF_NAMESIZE];
|
||||||
if (if_indextoname(sll.sll_ifindex, interfaceName) == NULL) {
|
if (if_indextoname(sll.sll_ifindex, interfaceName) == NULL) {
|
||||||
@ -312,22 +400,9 @@ static void read_rx_callback(int fd, short event, void *arg)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::string intf(interfaceName);
|
std::string intf(interfaceName);
|
||||||
auto vlan = vlan_map.find(intf);
|
context = interface_to_dev_context(devices, intf);
|
||||||
if (vlan == vlan_map.end()) {
|
if (context) {
|
||||||
if (intf.find(CLIENT_IF_PREFIX) != std::string::npos) {
|
client_packet_handler(context, rx_recv_buffer, buffer_sz, DHCP_RX);
|
||||||
syslog(LOG_WARNING, "invalid input interface %s\n", interfaceName);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dual_tor_sock) {
|
|
||||||
std::string state;
|
|
||||||
mStateDbMuxTablePtr->hget(intf, "state", state);
|
|
||||||
if (state != "standby") {
|
|
||||||
client_packet_handler(context, buffer_sz);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
client_packet_handler(context, buffer_sz);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -500,24 +575,20 @@ static void dhcp_print_counters(const char *vlan_intf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code init_socket(context, intf);
|
* @code init_socket();
|
||||||
*
|
*
|
||||||
* @brief initializes socket, bind it to interface and bpf program, and
|
* @brief initializes rx/tx sockets, bind it to interface and bpf program
|
||||||
* associate with libevent base
|
|
||||||
*
|
|
||||||
* @param context pointer to device (interface) context
|
|
||||||
* @param intf interface name
|
|
||||||
*
|
*
|
||||||
* @return 0 on success, otherwise for failure
|
* @return 0 on success, otherwise for failure
|
||||||
*/
|
*/
|
||||||
static int init_socket(dhcp_device_context_t *context, const char *intf)
|
static int init_socket()
|
||||||
{
|
{
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
context->rx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL));
|
auto rx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL));
|
||||||
context->tx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL));
|
auto tx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL));
|
||||||
if (context->rx_sock < 0 || context->tx_sock < 0) {
|
if (rx_sock < 0 || tx_sock < 0) {
|
||||||
syslog(LOG_ALERT, "socket: failed to open socket with '%s'\n", strerror(errno));
|
syslog(LOG_ALERT, "socket: failed to open socket with '%s'\n", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -527,30 +598,47 @@ static int init_socket(dhcp_device_context_t *context, const char *intf)
|
|||||||
rx_addr.sll_ifindex = 0; // any interface
|
rx_addr.sll_ifindex = 0; // any interface
|
||||||
rx_addr.sll_family = AF_PACKET;
|
rx_addr.sll_family = AF_PACKET;
|
||||||
rx_addr.sll_protocol = htons(ETH_P_ALL);
|
rx_addr.sll_protocol = htons(ETH_P_ALL);
|
||||||
if (bind(context->rx_sock, (struct sockaddr *) &rx_addr, sizeof(rx_addr))) {
|
if (bind(rx_sock, (struct sockaddr *) &rx_addr, sizeof(rx_addr))) {
|
||||||
syslog(LOG_ALERT, "bind: failed to bind to interface '%s' with '%s'\n", intf, strerror(errno));
|
syslog(LOG_ALERT, "bind: failed to bind to all interface with '%s'\n", strerror(errno));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sockaddr_ll tx_addr;
|
struct sockaddr_ll tx_addr;
|
||||||
memset(&tx_addr, 0, sizeof(tx_addr));
|
memset(&tx_addr, 0, sizeof(tx_addr));
|
||||||
tx_addr.sll_ifindex = if_nametoindex(intf);
|
tx_addr.sll_ifindex = 0; // any interface
|
||||||
tx_addr.sll_family = AF_PACKET;
|
tx_addr.sll_family = AF_PACKET;
|
||||||
tx_addr.sll_protocol = htons(ETH_P_ALL);
|
tx_addr.sll_protocol = htons(ETH_P_ALL);
|
||||||
if (bind(context->tx_sock, (struct sockaddr *) &tx_addr, sizeof(tx_addr))) {
|
if (bind(tx_sock, (struct sockaddr *) &tx_addr, sizeof(tx_addr))) {
|
||||||
syslog(LOG_ALERT, "bind: failed to bind to interface '%s' with '%s'\n", intf, strerror(errno));
|
syslog(LOG_ALERT, "bind: failed to bind to interface with '%s'\n", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(context->intf, intf, sizeof(context->intf) - 1);
|
for (auto &itr : intfs) {
|
||||||
context->intf[sizeof(context->intf) - 1] = '\0';
|
itr.second->dev_context->rx_sock = rx_sock;
|
||||||
|
itr.second->dev_context->tx_sock = tx_sock;
|
||||||
|
}
|
||||||
rv = 0;
|
rv = 0;
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_recv_buffers(int snaplen)
|
||||||
|
{
|
||||||
|
snap_length = snaplen;
|
||||||
|
rx_recv_buffer = (uint8_t *) malloc(snaplen);
|
||||||
|
if (rx_recv_buffer == NULL) {
|
||||||
|
syslog(LOG_ALERT, "malloc: failed to allocate memory for socket rx buffer '%s'\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_recv_buffer = (uint8_t *) malloc(snaplen);
|
||||||
|
if (tx_recv_buffer == NULL) {
|
||||||
|
syslog(LOG_ALERT, "malloc: failed to allocate memory for socket tx buffer '%s'\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code initialize_intf_mac_and_ip_addr(context);
|
* @code initialize_intf_mac_and_ip_addr(context);
|
||||||
*
|
*
|
||||||
@ -642,16 +730,15 @@ int dhcp_device_init(dhcp_device_context_t **context, const char *intf, uint8_t
|
|||||||
dhcp_device_context_t *dev_context = NULL;
|
dhcp_device_context_t *dev_context = NULL;
|
||||||
|
|
||||||
if ((context != NULL) && (strlen(intf) < sizeof(dev_context->intf))) {
|
if ((context != NULL) && (strlen(intf) < sizeof(dev_context->intf))) {
|
||||||
|
|
||||||
dev_context = (dhcp_device_context_t *) malloc(sizeof(dhcp_device_context_t));
|
dev_context = (dhcp_device_context_t *) malloc(sizeof(dhcp_device_context_t));
|
||||||
if (dev_context != NULL) {
|
if (dev_context != NULL) {
|
||||||
if ((init_socket(dev_context, intf) == 0) &&
|
// set device name
|
||||||
(initialize_intf_mac_and_ip_addr(dev_context) == 0)) {
|
strncpy(dev_context->intf, intf, sizeof(dev_context->intf) - 1);
|
||||||
|
dev_context->intf[sizeof(dev_context->intf) - 1] = '\0';
|
||||||
|
// set device meta data
|
||||||
|
if (initialize_intf_mac_and_ip_addr(dev_context) == 0) {
|
||||||
dev_context->is_uplink = is_uplink;
|
dev_context->is_uplink = is_uplink;
|
||||||
|
|
||||||
memset(dev_context->counters, 0, sizeof(dev_context->counters));
|
memset(dev_context->counters, 0, sizeof(dev_context->counters));
|
||||||
|
|
||||||
*context = dev_context;
|
*context = dev_context;
|
||||||
rv = 0;
|
rv = 0;
|
||||||
}
|
}
|
||||||
@ -665,53 +752,55 @@ int dhcp_device_init(dhcp_device_context_t **context, const char *intf, uint8_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code dhcp_device_start_capture(context, snaplen, base, giaddr_ip);
|
* @code dhcp_device_start_capture(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(size_t snaplen, struct event_base *base, in_addr_t giaddr_ip)
|
||||||
size_t snaplen,
|
|
||||||
struct event_base *base,
|
|
||||||
in_addr_t giaddr_ip)
|
|
||||||
{
|
{
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
struct event *rx_ev;
|
struct event *rx_ev;
|
||||||
struct event *tx_ev;
|
struct event *tx_ev;
|
||||||
|
int rx_sock = -1, tx_sock = -1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (context == NULL) {
|
|
||||||
syslog(LOG_ALERT, "NULL interface context pointer'\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snaplen < UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) {
|
if (snaplen < UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) {
|
||||||
syslog(LOG_ALERT, "dhcp_device_start_capture(%s): snap length is too low to capture DHCP options", context->intf);
|
syslog(LOG_ALERT, "dhcp_device_start_capture: snap length is too low to capture DHCP options");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
context->giaddr_ip = giaddr_ip;
|
init_socket();
|
||||||
|
|
||||||
context->buffer = (uint8_t *) malloc(snaplen);
|
init_recv_buffers(snaplen);
|
||||||
if (context->buffer == NULL) {
|
|
||||||
syslog(LOG_ALERT, "malloc: failed to allocate memory for socket buffer '%s'\n", strerror(errno));
|
update_vlan_mapping(mConfigDbPtr);
|
||||||
|
update_portchannel_mapping(mConfigDbPtr);
|
||||||
|
update_mgmt_mapping();
|
||||||
|
|
||||||
|
for (auto &itr : intfs) {
|
||||||
|
itr.second->dev_context->snaplen = snaplen;
|
||||||
|
itr.second->dev_context->giaddr_ip = giaddr_ip;
|
||||||
|
// all interface dev context has same rx/tx socket
|
||||||
|
rx_sock = itr.second->dev_context->rx_sock;
|
||||||
|
tx_sock = itr.second->dev_context->tx_sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rx_sock == -1 || tx_sock == -1) {
|
||||||
|
syslog(LOG_ALERT, "dhcp_device_start_capture: invalid rx_sock or tx_sock");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
context->snaplen = snaplen;
|
if (setsockopt(rx_sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_inbound_sock_bfp, sizeof(dhcp_inbound_sock_bfp)) != 0) {
|
||||||
|
|
||||||
if (setsockopt(context->rx_sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_inbound_sock_bfp, sizeof(dhcp_inbound_sock_bfp)) != 0) {
|
|
||||||
syslog(LOG_ALERT, "setsockopt: failed to attach filter with '%s'\n", strerror(errno));
|
syslog(LOG_ALERT, "setsockopt: failed to attach filter with '%s'\n", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsockopt(context->tx_sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_outbound_sock_bfp, sizeof(dhcp_outbound_sock_bfp)) != 0) {
|
if (setsockopt(tx_sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_outbound_sock_bfp, sizeof(dhcp_outbound_sock_bfp)) != 0) {
|
||||||
syslog(LOG_ALERT, "setsockopt: failed to attach filter with '%s'\n", strerror(errno));
|
syslog(LOG_ALERT, "setsockopt: failed to attach filter with '%s'\n", strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_vlan_mapping(context->intf, mConfigDbPtr);
|
rx_ev = event_new(base, rx_sock, EV_READ | EV_PERSIST, read_rx_callback, &intfs);
|
||||||
|
tx_ev = event_new(base, tx_sock, EV_READ | EV_PERSIST, read_tx_callback, &intfs);
|
||||||
rx_ev = event_new(base, context->rx_sock, EV_READ | EV_PERSIST, read_rx_callback, context);
|
|
||||||
tx_ev = event_new(base, context->tx_sock, EV_READ | EV_PERSIST, read_tx_callback, context);
|
|
||||||
|
|
||||||
if (rx_ev == NULL || tx_ev == NULL) {
|
if (rx_ev == NULL || tx_ev == NULL) {
|
||||||
syslog(LOG_ALERT, "event_new: failed to allocate memory for libevent event '%s'\n", strerror(errno));
|
syslog(LOG_ALERT, "event_new: failed to allocate memory for libevent event '%s'\n", strerror(errno));
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <event2/buffer.h>
|
#include <event2/buffer.h>
|
||||||
|
|
||||||
extern bool dual_tor_sock;
|
extern bool dual_tor_sock;
|
||||||
|
extern std::unordered_map<std::string, struct intf*> intfs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DHCP message types
|
* DHCP message types
|
||||||
@ -83,7 +84,6 @@ typedef struct
|
|||||||
in_addr_t giaddr_ip; /** Gateway 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 */
|
|
||||||
size_t snaplen; /** snap length or buffer size */
|
size_t snaplen; /** snap length or buffer size */
|
||||||
uint64_t counters[DHCP_COUNTERS_COUNT][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT];
|
uint64_t counters[DHCP_COUNTERS_COUNT][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT];
|
||||||
/** current/snapshot counters of DHCP packets */
|
/** current/snapshot counters of DHCP packets */
|
||||||
@ -137,21 +137,17 @@ 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, giaddr_ip);
|
* @code dhcp_device_start_capture(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 snaplen length of packet capture
|
* @param snaplen length of packet capture
|
||||||
* @param base pointer to libevent base
|
* @param base pointer to libevent base
|
||||||
* @param giaddr_ip gateway 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(size_t snaplen, struct event_base *base, in_addr_t giaddr_ip);
|
||||||
size_t snaplen,
|
|
||||||
struct event_base *base,
|
|
||||||
in_addr_t giaddr_ip);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code dhcp_device_shutdown(context);
|
* @code dhcp_device_shutdown(context);
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/queue.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "dhcp_devman.h"
|
#include "dhcp_devman.h"
|
||||||
@ -15,17 +14,8 @@
|
|||||||
/** Prefix appended to Aggregation device */
|
/** Prefix appended to Aggregation device */
|
||||||
#define AGG_DEV_PREFIX "Agg-"
|
#define AGG_DEV_PREFIX "Agg-"
|
||||||
|
|
||||||
/** struct for interface information */
|
/** intfs map of interfaces */
|
||||||
struct intf
|
std::unordered_map<std::string, struct intf*> intfs;
|
||||||
{
|
|
||||||
const char *name; /** interface name */
|
|
||||||
uint8_t is_uplink; /** is uplink (north) interface */
|
|
||||||
dhcp_device_context_t *dev_context; /** device (interface_ context */
|
|
||||||
LIST_ENTRY(intf) entry; /** list link/pointers entries */
|
|
||||||
};
|
|
||||||
|
|
||||||
/** intfs list of interfaces */
|
|
||||||
static LIST_HEAD(intf_list, intf) intfs;
|
|
||||||
/** dhcp_num_south_intf number of south interfaces */
|
/** dhcp_num_south_intf number of south interfaces */
|
||||||
static uint32_t dhcp_num_south_intf = 0;
|
static uint32_t dhcp_num_south_intf = 0;
|
||||||
/** dhcp_num_north_intf number of north interfaces */
|
/** dhcp_num_north_intf number of north interfaces */
|
||||||
@ -66,17 +56,6 @@ dhcp_device_context_t* dhcp_devman_get_mgmt_dev()
|
|||||||
return mgmt_intf ? mgmt_intf->dev_context : NULL;
|
return mgmt_intf ? mgmt_intf->dev_context : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @code dhcp_devman_init();
|
|
||||||
*
|
|
||||||
* initializes device (interface) manager that keeps track of interfaces and assert that there is one south
|
|
||||||
* interface and as many north interfaces
|
|
||||||
*/
|
|
||||||
void dhcp_devman_init()
|
|
||||||
{
|
|
||||||
LIST_INIT(&intfs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code dhcp_devman_shutdown();
|
* @code dhcp_devman_shutdown();
|
||||||
*
|
*
|
||||||
@ -85,20 +64,11 @@ void dhcp_devman_init()
|
|||||||
*/
|
*/
|
||||||
void dhcp_devman_shutdown()
|
void dhcp_devman_shutdown()
|
||||||
{
|
{
|
||||||
struct intf *int_ptr, *prev_intf = NULL;
|
for (auto it = intfs.begin(); it != intfs.end();) {
|
||||||
|
auto inf = it->second;
|
||||||
LIST_FOREACH(int_ptr, &intfs, entry) {
|
dhcp_device_shutdown(inf->dev_context);
|
||||||
dhcp_device_shutdown(int_ptr->dev_context);
|
it = intfs.erase(it);
|
||||||
if (prev_intf) {
|
free(inf);
|
||||||
LIST_REMOVE(prev_intf, entry);
|
|
||||||
free(prev_intf);
|
|
||||||
prev_intf = int_ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prev_intf) {
|
|
||||||
LIST_REMOVE(prev_intf, entry);
|
|
||||||
free(prev_intf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,12 +110,14 @@ int dhcp_devman_add_intf(const char *name, char intf_type)
|
|||||||
|
|
||||||
dhcp_device_context_t *agg_dev = dhcp_device_get_aggregate_context();
|
dhcp_device_context_t *agg_dev = dhcp_device_get_aggregate_context();
|
||||||
|
|
||||||
strncpy(agg_dev->intf, AGG_DEV_PREFIX, sizeof(AGG_DEV_PREFIX));
|
strncpy(agg_dev->intf, AGG_DEV_PREFIX, strlen(AGG_DEV_PREFIX) + 1);
|
||||||
strncpy(agg_dev->intf + sizeof(AGG_DEV_PREFIX) - 1, name, sizeof(agg_dev->intf) - sizeof(AGG_DEV_PREFIX));
|
strncpy(agg_dev->intf + strlen(AGG_DEV_PREFIX), name, sizeof(agg_dev->intf) - strlen(AGG_DEV_PREFIX) - 1);
|
||||||
agg_dev->intf[sizeof(agg_dev->intf) - 1] = '\0';
|
agg_dev->intf[sizeof(agg_dev->intf) - 1] = '\0';
|
||||||
|
syslog(LOG_INFO, "dhcpmon add aggregate interface '%s'\n", agg_dev->intf);
|
||||||
}
|
}
|
||||||
|
std::string if_name;
|
||||||
LIST_INSERT_HEAD(&intfs, dev, entry);
|
if_name.assign(dev->name);
|
||||||
|
intfs[if_name] = dev;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
syslog(LOG_ALERT, "malloc: failed to allocate memory for intf '%s'\n", name);
|
syslog(LOG_ALERT, "malloc: failed to allocate memory for intf '%s'\n", name);
|
||||||
@ -193,21 +165,12 @@ int dhcp_devman_setup_dual_tor_mode(const char *name)
|
|||||||
int dhcp_devman_start_capture(size_t snaplen, struct event_base *base)
|
int dhcp_devman_start_capture(size_t snaplen, struct event_base *base)
|
||||||
{
|
{
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
struct intf *int_ptr;
|
|
||||||
|
|
||||||
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) {
|
rv = dhcp_device_start_capture(snaplen, base, dual_tor_mode ? loopback_ip : 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_ALERT, "Capturing DHCP packets on interface failed");
|
||||||
syslog(LOG_INFO,
|
exit(1);
|
||||||
"Capturing DHCP packets on interface %s, ip: 0x%08x, mac [%02x:%02x:%02x:%02x:%02x:%02x] \n",
|
|
||||||
int_ptr->name, int_ptr->dev_context->ip, int_ptr->dev_context->mac[0],
|
|
||||||
int_ptr->dev_context->mac[1], int_ptr->dev_context->mac[2], int_ptr->dev_context->mac[3],
|
|
||||||
int_ptr->dev_context->mac[4], int_ptr->dev_context->mac[5]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -236,12 +199,9 @@ dhcp_mon_status_t dhcp_devman_get_status(dhcp_mon_check_t check_type, dhcp_devic
|
|||||||
void dhcp_devman_update_snapshot(dhcp_device_context_t *context)
|
void dhcp_devman_update_snapshot(dhcp_device_context_t *context)
|
||||||
{
|
{
|
||||||
if (context == NULL) {
|
if (context == NULL) {
|
||||||
struct intf *int_ptr;
|
for (auto &itr : intfs) {
|
||||||
|
dhcp_device_update_snapshot(itr.second->dev_context);
|
||||||
LIST_FOREACH(int_ptr, &intfs, entry) {
|
|
||||||
dhcp_device_update_snapshot(int_ptr->dev_context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dhcp_device_update_snapshot(dhcp_devman_get_agg_dev());
|
dhcp_device_update_snapshot(dhcp_devman_get_agg_dev());
|
||||||
} else {
|
} else {
|
||||||
dhcp_device_update_snapshot(context);
|
dhcp_device_update_snapshot(context);
|
||||||
@ -256,12 +216,9 @@ void dhcp_devman_update_snapshot(dhcp_device_context_t *context)
|
|||||||
void dhcp_devman_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type)
|
void dhcp_devman_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type)
|
||||||
{
|
{
|
||||||
if (context == NULL) {
|
if (context == NULL) {
|
||||||
struct intf *int_ptr;
|
for (auto &itr : intfs) {
|
||||||
|
dhcp_device_print_status(itr.second->dev_context, type);
|
||||||
LIST_FOREACH(int_ptr, &intfs, entry) {
|
|
||||||
dhcp_device_print_status(int_ptr->dev_context, type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dhcp_device_print_status(dhcp_devman_get_agg_dev(), type);
|
dhcp_device_print_status(dhcp_devman_get_agg_dev(), type);
|
||||||
} else {
|
} else {
|
||||||
dhcp_device_print_status(context, type);
|
dhcp_device_print_status(context, type);
|
||||||
|
@ -8,9 +8,19 @@
|
|||||||
#define DHCP_DEVMAN_H_
|
#define DHCP_DEVMAN_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "dhcp_device.h"
|
#include "dhcp_device.h"
|
||||||
|
|
||||||
|
/** struct for interface information */
|
||||||
|
struct intf
|
||||||
|
{
|
||||||
|
const char *name; /** interface name */
|
||||||
|
uint8_t is_uplink; /** is uplink (north) interface */
|
||||||
|
dhcp_device_context_t *dev_context; /** device (interface_ context */
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code dhcp_devman_init();
|
* @code dhcp_devman_init();
|
||||||
*
|
*
|
||||||
|
@ -29,6 +29,8 @@ typedef struct
|
|||||||
static int window_interval_sec = 18;
|
static int window_interval_sec = 18;
|
||||||
/** dhcp_unhealthy_max_count max count of consecutive unhealthy statuses before reporting to syslog */
|
/** dhcp_unhealthy_max_count max count of consecutive unhealthy statuses before reporting to syslog */
|
||||||
static int dhcp_unhealthy_max_count = 10;
|
static int dhcp_unhealthy_max_count = 10;
|
||||||
|
/** dhcpmon debug mode control flag */
|
||||||
|
static bool debug_on = false;
|
||||||
/** libevent base struct */
|
/** libevent base struct */
|
||||||
static struct event_base *base;
|
static struct event_base *base;
|
||||||
/** libevent timeout event struct */
|
/** libevent timeout event struct */
|
||||||
@ -132,6 +134,11 @@ static void timeout_callback(evutil_socket_t fd, short event, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dhcp_devman_update_snapshot(NULL);
|
dhcp_devman_update_snapshot(NULL);
|
||||||
|
|
||||||
|
if (debug_on) {
|
||||||
|
dhcp_devman_print_status(NULL, DHCP_COUNTERS_SNAPSHOT);
|
||||||
|
dhcp_devman_print_status(NULL, DHCP_COUNTERS_CURRENT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -206,13 +213,14 @@ void dhcp_mon_shutdown()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code dhcp_mon_start(snaplen);
|
* @code dhcp_mon_start(snaplen, debug_mode);
|
||||||
*
|
*
|
||||||
* @brief start monitoring DHCP Relay
|
* @brief start monitoring DHCP Relay
|
||||||
*/
|
*/
|
||||||
int dhcp_mon_start(size_t snaplen)
|
int dhcp_mon_start(size_t snaplen, bool debug_mode)
|
||||||
{
|
{
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
|
debug_on = debug_mode;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -245,7 +253,6 @@ int dhcp_mon_start(size_t snaplen)
|
|||||||
syslog(LOG_ERR, "Could not start libevent dispatching loop!\n");
|
syslog(LOG_ERR, "Could not start libevent dispatching loop!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = 0;
|
rv = 0;
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
@ -32,15 +32,16 @@ int dhcp_mon_init(int window_sec, int max_count);
|
|||||||
void dhcp_mon_shutdown();
|
void dhcp_mon_shutdown();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code dhcp_mon_start(snaplen);
|
* @code dhcp_mon_start(snaplen, debug);
|
||||||
*
|
*
|
||||||
* @brief start monitoring DHCP Relay
|
* @brief start monitoring DHCP Relay
|
||||||
*
|
*
|
||||||
* @param snaplen packet capture length
|
* @param snaplen packet capture length
|
||||||
|
* @param debug turn on debug or not
|
||||||
*
|
*
|
||||||
* @return 0 upon success, otherwise upon failure
|
* @return 0 upon success, otherwise upon failure
|
||||||
*/
|
*/
|
||||||
int dhcp_mon_start(size_t snaplen);
|
int dhcp_mon_start(size_t snaplen, bool debug);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @code dhcp_mon_stop();
|
* @code dhcp_mon_stop();
|
||||||
|
@ -46,7 +46,7 @@ bool dual_tor_sock = false;
|
|||||||
static void usage(const char *prog)
|
static void usage(const char *prog)
|
||||||
{
|
{
|
||||||
printf("Usage: %s -id <south interface> {-iu <north interface>}+ -im <mgmt interface> [-u <loopback interface>]"
|
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);
|
"[-w <snapshot window in sec>] [-c <unhealthy status count>] [-s <snap length>] [-D] [-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");
|
||||||
@ -57,6 +57,7 @@ static void usage(const char *prog)
|
|||||||
"(default %d),\n",
|
"(default %d),\n",
|
||||||
dhcpmon_default_unhealthy_max_count);
|
dhcpmon_default_unhealthy_max_count);
|
||||||
printf("\tsnap length: snap length of packet capture (default %ld),\n", dhcpmon_default_snaplen);
|
printf("\tsnap length: snap length of packet capture (default %ld),\n", dhcpmon_default_snaplen);
|
||||||
|
printf("\t-D: debug mode: print counter to syslog\n");
|
||||||
printf("\t-d: daemonize %s.\n", prog);
|
printf("\t-d: daemonize %s.\n", prog);
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
@ -117,12 +118,11 @@ int main(int argc, char **argv)
|
|||||||
int max_unhealthy_count = dhcpmon_default_unhealthy_max_count;
|
int max_unhealthy_count = dhcpmon_default_unhealthy_max_count;
|
||||||
size_t snaplen = dhcpmon_default_snaplen;
|
size_t snaplen = dhcpmon_default_snaplen;
|
||||||
int make_daemon = 0;
|
int make_daemon = 0;
|
||||||
|
bool debug_mode = false;
|
||||||
|
|
||||||
setlogmask(LOG_UPTO(LOG_INFO));
|
setlogmask(LOG_UPTO(LOG_INFO));
|
||||||
openlog(basename(argv[0]), LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
openlog(basename(argv[0]), LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON);
|
||||||
|
|
||||||
dhcp_devman_init();
|
|
||||||
|
|
||||||
for (i = 1; i < argc;) {
|
for (i = 1; i < argc;) {
|
||||||
if ((argv[i] == NULL) || (argv[i][0] != '-')) {
|
if ((argv[i] == NULL) || (argv[i][0] != '-')) {
|
||||||
break;
|
break;
|
||||||
@ -161,6 +161,10 @@ int main(int argc, char **argv)
|
|||||||
max_unhealthy_count = atoi(argv[i + 1]);
|
max_unhealthy_count = atoi(argv[i + 1]);
|
||||||
i += 2;
|
i += 2;
|
||||||
break;
|
break;
|
||||||
|
case 'D':
|
||||||
|
debug_mode = true;
|
||||||
|
i += 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "%s: %c: Unknown option\n", basename(argv[0]), argv[i][1]);
|
fprintf(stderr, "%s: %c: Unknown option\n", basename(argv[0]), argv[i][1]);
|
||||||
usage(basename(argv[0]));
|
usage(basename(argv[0]));
|
||||||
@ -172,7 +176,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((dhcp_mon_init(window_interval, max_unhealthy_count) == 0) &&
|
if ((dhcp_mon_init(window_interval, max_unhealthy_count) == 0) &&
|
||||||
(dhcp_mon_start(snaplen) == 0)) {
|
(dhcp_mon_start(snaplen, debug_mode) == 0)) {
|
||||||
|
|
||||||
rv = EXIT_SUCCESS;
|
rv = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user