Incorporate dhcp6relay into dhcp_relay docker

This commit is contained in:
kellyyeh 2021-10-15 22:36:38 +00:00 committed by Ying Xie
parent e5b7b8c05e
commit e134f1592e
25 changed files with 189 additions and 113 deletions

View File

@ -1 +1 @@
group:isc-dhcp-relay
group:dhcp-relay

View File

@ -1,16 +1,16 @@
[group:isc-dhcp-relay]
[group:dhcp-relay]
programs=
{%- set add_preceding_comma = { 'flag': False } %}
{% for vlan_name in vlan_list %}
{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %}
{% if add_preceding_comma.flag %},{% endif %}
{% set _dummy = add_preceding_comma.update({'flag': True}) %}
isc-dhcp-relayv4-{{ vlan_name }}
isc-dhcpv4-relay-{{ vlan_name }}
{%- endif %}
{# Append DHCPv6 agents #}
{% if VLAN and vlan_name in VLAN and 'dhcpv6_servers' in VLAN[vlan_name] %}
{% if add_preceding_comma.flag %},{% endif %}
{% set _dummy = add_preceding_comma.update({'flag': True}) %}
isc-dhcpv6-relay-{{ vlan_name }}
dhcp6relay
{%- endif %}
{% endfor %}

View File

@ -2,6 +2,13 @@
{# Create a program entry for each DHCP relay agent instance #}
{% for vlan_name in vlan_list %}
{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{% if dhcp_server | ipv4 %}
{% set _dummy = relay_for_ipv4.update({'flag': True}) %}
{% endif %}
{% endfor %}
{% if relay_for_ipv4.flag %}
{% set _dummy = relay_for_ipv4.update({'flag': False}) %}
[program:isc-dhcpv4-relay-{{ vlan_name }}]
{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #}
command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id {{ vlan_name }}
@ -23,5 +30,6 @@ autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
{% endif %}
{% endif %}
{% endfor %}

View File

@ -2,25 +2,15 @@
{# Create a program entry for each DHCPv6 relay agent instance #}
{% for vlan_name in vlan_list %}
{% if VLAN and vlan_name in VLAN and 'dhcpv6_servers' in VLAN[vlan_name] %}
{% for dhcpv6_server in VLAN[vlan_name]['dhcpv6_servers'] %}
{% if dhcpv6_server | ipv6 %}
{% set _dummy = relay_for_ipv6.update({'flag': True}) %}
{% endif %}
{% endfor %}
{% if relay_for_ipv6.flag %}
{% set _dummy = relay_for_ipv6.update({'flag': False}) %}
{% endif %}
[program:isc-dhcpv6-relay-{{ vlan_name }}]
{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #}
command=/usr/sbin/dhcrelay -d -6 --name-alias-map-file /tmp/port-name-alias-map.txt -l {{ vlan_name }}
{#- We treat all other interfaces as upstream interfaces (-iu), as we only want to listen for replies #}
{% for (name, prefix) in VLAN_INTERFACE %}
{% if prefix | ipv6 and name != vlan_name %} -u {{ dhcpv6_server }}%%{{ name }} {% endif -%}
{% endfor %}
{% for (name, prefix) in INTERFACE %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for (name, prefix) in PORTCHANNEL_INTERFACE %}
{% if prefix | ipv4 %} -iu {{ name }} {% endif -%}
{% endfor %}
[program:dhcp6relay]
command=/usr/sbin/dhcp6relay
priority=3
autostart=false
@ -28,5 +18,6 @@ autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
{% endif %}
{% endif %}
{% endfor %}

View File

@ -1,11 +1,19 @@
[group:dhcpmon]
programs=
{%- set add_preceding_comma = { 'flag': False } %}
{% set monitor_instance = { 'flag': False } %}
{% for vlan_name in vlan_list %}
{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %}
{% set _dummy = monitor_instance.update({'flag': True}) %}
{%- endif %}
{% if VLAN and vlan_name in VLAN and 'dhcpv6_servers' in VLAN[vlan_name] %}
{% set _dummy = monitor_instance.update({'flag': True}) %}
{% endif %}
{% if monitor_instance.flag %}
{% if add_preceding_comma.flag %},{% endif %}
{% set _dummy = add_preceding_comma.update({'flag': True}) %}
dhcpmon-{{ vlan_name }}
{%- set _dummy = monitor_instance.update({'flag': False}) %}
{%- endif %}
{% endfor %}
@ -60,8 +68,6 @@ autostart=false
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
{%- if relay_for_ipv4.flag %}isc-dhcpv4-relay-{{ vlan_name }}:running {% endif %}
{% if relay_for_ipv6.flag %}isc-dhcpv6-relay-{{ vlan_name }}:running{% endif %}
{% set _dummy = relay_for_ipv4.update({'flag': False}) %}

View File

@ -21,6 +21,9 @@ stderr_logfile=syslog
{# If our configuration has VLANs... #}
{% if VLAN_INTERFACE %}
{# Count how many VLANs require a DHCP relay agent... #}
{% set ipv4_num_relays = { 'count': 0 } %}
{% set ipv6_num_relays = { 'count': 0 } %}
{% set d = namespace(vlan_list=[]) %}
{% for (name, prefix) in VLAN_INTERFACE %}
{% if name not in d.vlan_list %}
@ -32,20 +35,21 @@ stderr_logfile=syslog
{% set num_relays = { 'count': 0 } %}
{% for vlan_name in vlan_list %}
{% if VLAN and vlan_name in VLAN and VLAN[vlan_name]['dhcp_servers'] %}
{% set _dummy = num_relays.update({'count': num_relays.count + 1}) %}
{% set _dummy = ipv4_num_relays.update({'count': ipv4_num_relays.count + 1}) %}
{% endif %}
{% if VLAN and vlan_name in VLAN and 'dhcpv6_servers' in VLAN[vlan_name] %}
{% set _dummy = ipv6_num_relays.update({'count': ipv6_num_relays.count + 1}) %}
{% endif %}
{% endfor %}
{# If one or more of the VLANs require a DHCP relay agent... #}
{% if num_relays.count > 0 %}
{% if ipv4_num_relays.count > 0 or ipv6_num_relays.count > 0 %}
{% include 'dhcp-relay.programs.j2' %}
{% set relay_for_ipv4 = { 'flag': False } %}
{% set relay_for_ipv6 = { 'flag': False } %}
{% for vlan_name in VLAN_INTERFACE %}
{% include 'dhcpv4-relay.agents.j2' %}
{% include 'dhcpv6-relay.agents.j2' %}
{% endfor %}
{% include 'dhcpv6-relay.monitors.j2' %}
{% endif %}

View File

@ -7,7 +7,7 @@ rm -f /var/run/rsyslogd.pid
supervisorctl start rsyslogd
# If our supervisor config has entries in the "isc-dhcp-relay" group...
if [ $(supervisorctl status | grep -c "^isc-dhcp-relay:") -gt 0 ]; then
if [ $(supervisorctl status | grep -c "^dhcp-relay:") -gt 0 ]; then
# Wait for all interfaces to come up and be assigned IPv4 addresses before
# starting the DHCP relay agent(s). If an interface the relay should listen
# on is down, the relay agent will not start. If an interface the relay
@ -17,7 +17,7 @@ if [ $(supervisorctl status | grep -c "^isc-dhcp-relay:") -gt 0 ]; then
/usr/bin/wait_for_intf.sh
# Start all DHCP relay agent(s)
supervisorctl start isc-dhcp-relay:*
supervisorctl start dhcp-relay:*
fi
# If our supervisor config has entries in the "dhcpmon" group...

9
rules/dhcp6relay.mk Normal file
View File

@ -0,0 +1,9 @@
# SONiC DHCPV6 RELAY Package
SONIC_DHCP6RELAY_VERSION = 1.0.0-0
SONIC_DHCP6RELAY_PKG_NAME = dhcp6relay
SONIC_DHCP6RELAY = sonic-$(SONIC_DHCP6RELAY_PKG_NAME)_$(SONIC_DHCP6RELAY_VERSION)_amd64.deb
$(SONIC_DHCP6RELAY)_DEPENDS = $(LIBSWSSCOMMON) $(LIBHIREDIS) $(LIBSWSSCOMMON_DEV) $(LIBHIREDIS_DEV)
$(SONIC_DHCP6RELAY)_SRC_PATH = $(SRC_PATH)/$(SONIC_DHCP6RELAY_PKG_NAME)
SONIC_DPKG_DEBS += $(SONIC_DHCP6RELAY)

View File

@ -6,7 +6,7 @@ DOCKER_DHCP_RELAY_DBG = $(DOCKER_DHCP_RELAY_STEM)-$(DBG_IMAGE_MARK).gz
$(DOCKER_DHCP_RELAY)_PATH = $(DOCKERS_PATH)/docker-dhcp-relay
$(DOCKER_DHCP_RELAY)_DEPENDS += $(ISC_DHCP_COMMON) $(ISC_DHCP_RELAY) $(REDIS_TOOLS) $(SONIC_DHCPMON)
$(DOCKER_DHCP_RELAY)_DEPENDS += $(ISC_DHCP_COMMON) $(ISC_DHCP_RELAY) $(REDIS_TOOLS) $(SONIC_DHCPMON) $(SONIC_DHCP6RELAY) $(LIBSWSSCOMMON)
$(DOCKER_DHCP_RELAY)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE)_DBG_DEPENDS)
$(DOCKER_DHCP_RELAY)_DBG_DEPENDS += $(ISC_DHCP_DBG)
$(DOCKER_DHCP_RELAY)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE)_DBG_IMAGE_PACKAGES)

View File

@ -242,7 +242,11 @@ RUN apt-get update && apt-get install -y \
qemu-kvm \
libvirt-bin \
# For DHCP Monitor tool
libevent-dev
libevent-dev \
# For DHCPv6 Relay
libboost-dev \
libboost-thread1.55.0 \
libboost-system1.55.0
# For linux build
RUN apt-get -y build-dep linux

View File

@ -4,7 +4,7 @@ CP := cp
MKDIR := mkdir
CC := g++
MV := mv
LIBS := -levent -lhiredis -lswsscommon -pthread -lboost_thread -lboost_system -I $(PWD)/../sonic-swss-common/common
LIBS := -levent -lswsscommon -pthread -lboost_thread -lboost_system -I $(PWD)/../sonic-swss-common/common
CFLAGS = -g -Wall -std=gnu11
PWD := $(shell pwd)

View File

@ -2,4 +2,4 @@ sonic-dhcp6relay (1.0.0-0) UNRELEASED; urgency=medium
* Initial release.
-- Kelly Yeh <kellyyeh@microsoft.com>
-- Kelly Yeh <kellyyeh@microsoft.com> Fri, 15 Oct 2021 00:00:00 +1000

View File

@ -11,7 +11,7 @@ XS-Go-Import-Path: github.com/Azure/sonic-buildimage
Package: sonic-dhcp6relay
Architecture: any
Built-Using: ${misc:Built-Using}
Depends: libevent-2.1-6,
libboost-thread1.71.0,
libboost-system1.71.0
Depends: libevent-2.0-5,
libboost-thread1.55.0,
libboost-system1.55.0
Description: SONiC DHCPv6 Relay

View File

@ -8,18 +8,18 @@ constexpr auto DEFAULT_TIMEOUT_MSEC = 1000;
bool pollSwssNotifcation = true;
std::shared_ptr<boost::thread> mSwssThreadPtr;
std::shared_ptr<swss::DBConnector> configDbPtr = std::make_shared<swss::DBConnector> ("CONFIG_DB", 0);
std::shared_ptr<swss::DBConnector> configDbPtr = std::make_shared<swss::DBConnector> (4, "localhost", 6379, 0);
swss::SubscriberStateTable ipHelpersTable(configDbPtr.get(), "DHCP_RELAY");
swss::Select swssSelect;
/**
* @code void deinitialize_swss()
* @code void initialize_swss()
*
* @brief initialize DB tables and start SWSS listening thread
*
* @return none
*/
void initialize_swss(std::vector<relay_config> *vlans, swss::DBConnector *db)
void initialize_swss(std::vector<relay_config> *vlans)
{
try {
swssSelect.addSelectable(&ipHelpersTable);
@ -85,7 +85,7 @@ void handleSwssNotification(std::vector<relay_config> *vlans)
* @brief handles DHCPv6 relay configuration change notification
*
* @param ipHelpersTable DHCP table
* @param context list of vlans/argument config that contains strings of server and option
* @param vlans list of vlans/argument config that contains strings of server and option
*
* @return none
*/
@ -103,7 +103,7 @@ void handleRelayNotification(swss::SubscriberStateTable &ipHelpersTable, std::ve
* @brief process DHCPv6 relay servers and options configuration change notification
*
* @param entries queue of std::tuple<std::string, std::string, std::vector<FieldValueTuple>> entries in DHCP table
* @param context list of vlans/argument config that contains strings of server and option
* @param vlans list of vlans/argument config that contains strings of server and option
*
* @return none
*/
@ -117,6 +117,7 @@ void processRelayNotification(std::deque<swss::KeyOpFieldsValuesTuple> &entries,
std::vector<swss::FieldValueTuple> fieldValues = kfvFieldsValues(entry);
relay_config intf;
intf.is_option_79 = true;
intf.interface = vlan;
for (auto &fieldValue: fieldValues) {
std::string f = fvField(fieldValue);
@ -130,11 +131,8 @@ void processRelayNotification(std::deque<swss::KeyOpFieldsValuesTuple> &entries,
}
syslog(LOG_DEBUG, "key: %s, Operation: %s, f: %s, v: %s", vlan.c_str(), operation.c_str(), f.c_str(), v.c_str());
}
if(f == "dhcpv6_option|rfc6939_support") {
if(v == "true")
intf.is_option_79 = true;
else if(v == "false")
intf.is_option_79 = false;
if(f == "dhcpv6_option|rfc6939_support" && v == "false") {
intf.is_option_79 = false;
}
}
vlans->push_back(intf);

View File

@ -4,13 +4,13 @@
#include "relay.h"
/**
* @code void deinitialize_swss()
* @code void initialize_swss()
*
* @brief initialize DB tables and start SWSS listening thread
*
* @return none
*/
void initialize_swss(std::vector<relay_config> *vlans, swss::DBConnector *db);
void initialize_swss(std::vector<relay_config> *vlans);
/**
* @code void deinitialize_swss()
@ -35,7 +35,7 @@ void get_dhcp(std::vector<relay_config> *vlans);
*
* @brief main thread for handling SWSS notification
*
* @param context list of vlans/argument config that contains strings of server and option
* @param vlans list of vlans/argument config that contains strings of server and option
*
* @return none
*/
@ -47,7 +47,7 @@ void handleSwssNotification(std::vector<relay_config> *vlans);
* @brief handles DHCPv6 relay configuration change notification
*
* @param ipHelpersTable DHCP table
* @param context list of vlans/argument config that contains strings of server and option
* @param vlans list of vlans/argument config that contains strings of server and option
*
* @return none
*/

View File

@ -5,8 +5,8 @@
int main(int argc, char *argv[]) {
try {
std::vector<relay_config> vlans;
swss::DBConnector state_db("STATE_DB", 0);
initialize_swss(&vlans, &state_db);
swss::DBConnector state_db(6, "localhost", 6379, 0);
initialize_swss(&vlans);
loop_relay(&vlans, &state_db);
}
catch (std::exception &e)

View File

@ -7,10 +7,9 @@
#include <syslog.h>
#include <signal.h>
#include "configdb.h"
#include "sonicv2connector.h"
#include "dbconnector.h"
#include "configInterface.h"
#include "table.h"
struct event *listen_event;
@ -18,6 +17,7 @@ struct event *server_listen_event;
struct event_base *base;
struct event *ev_sigint;
struct event *ev_sigterm;
static std::string counter_table = "DHCPv6_COUNTER_TABLE";
/* DHCPv6 filter */
/* sudo tcpdump -dd "ip6 dst ff02::1:2 && udp dst port 547" */
@ -61,7 +61,7 @@ std::map<int, std::string> counterMap = {{1, "Solicit"},
{13, "Relay-Reply"}};
/**
* @code void initialize_counter(swss::DBConnector *db, std::string counterVlan);
* @code void initialize_counter(swss::Table *table, std::string counterVlan);
*
* @brief initialize the counter by each Vlan
*
@ -70,33 +70,34 @@ std::map<int, std::string> counterMap = {{1, "Solicit"},
*
* @return none
*/
void initialize_counter(swss::DBConnector *db, std::string counterVlan) {
db->hset(counterVlan, "Solicit", toString(counters[DHCPv6_MESSAGE_TYPE_SOLICIT]));
db->hset(counterVlan, "Advertise", toString(counters[DHCPv6_MESSAGE_TYPE_ADVERTISE]));
db->hset(counterVlan, "Request", toString(counters[DHCPv6_MESSAGE_TYPE_REQUEST]));
db->hset(counterVlan, "Confirm", toString(counters[DHCPv6_MESSAGE_TYPE_CONFIRM]));
db->hset(counterVlan, "Renew", toString(counters[DHCPv6_MESSAGE_TYPE_RENEW]));
db->hset(counterVlan, "Rebind", toString(counters[DHCPv6_MESSAGE_TYPE_REBIND]));
db->hset(counterVlan, "Reply", toString(counters[DHCPv6_MESSAGE_TYPE_REPLY]));
db->hset(counterVlan, "Release", toString(counters[DHCPv6_MESSAGE_TYPE_RELEASE]));
db->hset(counterVlan, "Decline", toString(counters[DHCPv6_MESSAGE_TYPE_DECLINE]));
db->hset(counterVlan, "Relay-Forward", toString(counters[DHCPv6_MESSAGE_TYPE_RELAY_FORW]));
db->hset(counterVlan, "Relay-Reply", toString(counters[DHCPv6_MESSAGE_TYPE_RELAY_REPL]));
void initialize_counter(swss::Table *table, std::string counterVlan) {
table->hset(counterVlan, "Solicit", toString(counters[DHCPv6_MESSAGE_TYPE_SOLICIT]));
table->hset(counterVlan, "Solicit", toString(counters[DHCPv6_MESSAGE_TYPE_SOLICIT]));
table->hset(counterVlan, "Advertise", toString(counters[DHCPv6_MESSAGE_TYPE_ADVERTISE]));
table->hset(counterVlan, "Request", toString(counters[DHCPv6_MESSAGE_TYPE_REQUEST]));
table->hset(counterVlan, "Confirm", toString(counters[DHCPv6_MESSAGE_TYPE_CONFIRM]));
table->hset(counterVlan, "Renew", toString(counters[DHCPv6_MESSAGE_TYPE_RENEW]));
table->hset(counterVlan, "Rebind", toString(counters[DHCPv6_MESSAGE_TYPE_REBIND]));
table->hset(counterVlan, "Reply", toString(counters[DHCPv6_MESSAGE_TYPE_REPLY]));
table->hset(counterVlan, "Release", toString(counters[DHCPv6_MESSAGE_TYPE_RELEASE]));
table->hset(counterVlan, "Decline", toString(counters[DHCPv6_MESSAGE_TYPE_DECLINE]));
table->hset(counterVlan, "Relay-Forward", toString(counters[DHCPv6_MESSAGE_TYPE_RELAY_FORW]));
table->hset(counterVlan, "Relay-Reply", toString(counters[DHCPv6_MESSAGE_TYPE_RELAY_REPL]));
}
/**
* @code void update_counter(swss::DBConnector *db, std::string CounterVlan, uint8_t msg_type);
* @code void update_counter(swss::Table *table, std::string CounterVlan, uint8_t msg_type);
*
* @brief update the counter in state_db with count of each DHCPv6 message type
*
* @param swss::DBConnector *db state_db connector
* @param swss::Table table DHCPv6_COUNTER table
* @param counterVlan counter table with interface name
* @param msg_type dhcpv6 message type to be updated in counter
*
* @return none
*/
void update_counter(swss::DBConnector *db, std::string counterVlan, uint8_t msg_type) {
db->hset(counterVlan, counterMap.find(msg_type)->second, toString(counters[msg_type]));
void update_counter(swss::Table *table, std::string counterVlan, uint8_t msg_type) {
table->hset(counterVlan, counterMap.find(msg_type)->second, toString(counters[msg_type]));
}
/**
@ -325,12 +326,12 @@ int sock_open(int ifindex, const struct sock_fprog *fprog)
*
* @return none
*/
void prepare_relay_config(relay_config *interface_config, int local_sock, int filter) {
void prepare_relay_config(relay_config *interface_config, int *local_sock, int filter) {
struct ifaddrs *ifa, *ifa_tmp;
sockaddr_in6 non_link_local;
sockaddr_in6 link_local;
interface_config->local_sock = local_sock;
interface_config->local_sock = *local_sock;
interface_config->filter = filter;
for(auto server: interface_config->servers) {
@ -376,22 +377,20 @@ void prepare_relay_config(relay_config *interface_config, int local_sock, int fi
}
/**
* @code prepare_socket(int *local_sock, relay_config *config);
* @code prepare_socket(int *local_sock);
*
* @brief prepare L3 socket for sending
*
* @param local_sock pointer to socket to be prepared
* @param config relay config that contains strings of server and interface addresses
*
* @return none
*/
void prepare_socket(int *local_sock, relay_config *config, int index) {
void prepare_socket(int *local_sock) {
int flag = 1;
sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_scope_id = index;
addr.sin6_port = htons(RELAY_PORT);
if ((*local_sock = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) {
@ -434,11 +433,6 @@ void relay_client(int sock, const uint8_t *msg, int32_t len, const ip6_hdr *ip_h
memcpy(current_buffer_position, &new_message, sizeof(dhcpv6_relay_msg));
current_buffer_position += sizeof(dhcpv6_relay_msg);
auto dhcp_message_length = len;
relay_forward(current_buffer_position, parse_dhcpv6_hdr(msg), dhcp_message_length);
current_buffer_position += dhcp_message_length + sizeof(dhcpv6_option);
if(config->is_option_79) {
linklayer_addr_option option79;
option79.link_layer_type = htons(1);
@ -447,10 +441,14 @@ void relay_client(int sock, const uint8_t *msg, int32_t len, const ip6_hdr *ip_h
memcpy(current_buffer_position, &option79, sizeof(linklayer_addr_option));
current_buffer_position += sizeof(linklayer_addr_option);
memcpy(current_buffer_position, &ether_hdr->ether_shost, sizeof(ether_hdr->ether_shost));
current_buffer_position += sizeof(ether_hdr->ether_shost);
}
memcpy(current_buffer_position, &ether_hdr->ether_shost, sizeof(ether_hdr->ether_shost));
current_buffer_position += sizeof(ether_hdr->ether_shost);
auto dhcp_message_length = len;
relay_forward(current_buffer_position, parse_dhcpv6_hdr(msg), dhcp_message_length);
current_buffer_position += dhcp_message_length + sizeof(dhcpv6_option);
for(auto server: config->servers_sock) {
send_udp(sock, buffer, server, current_buffer_position - buffer);
@ -546,11 +544,23 @@ void callback(evutil_socket_t fd, short event, void *arg) {
auto msg = parse_dhcpv6_hdr(current_position);
counters[msg->msg_type]++;
update_counter(config->db, config->counterVlan, msg->msg_type);
std::string counterVlan = counter_table;
update_counter(config->table, counterVlan.append(config->interface), msg->msg_type);
relay_client(config->local_sock, current_position, ntohs(udp_header->len) - sizeof(udphdr), ip_header, ether_header, config);
}
/**
* @code void server_callback(evutil_socket_t fd, short event, void *arg);
*
* @brief callback for libevent that is called everytime data is received at the server socket
*
* @param fd filter socket
* @param event libevent triggered event
* @param arg callback argument provided by user
*
* @return none
*/
void server_callback(evutil_socket_t fd, short event, void *arg) {
struct relay_config *config = (struct relay_config *)arg;
sockaddr_in6 from;
@ -565,7 +575,8 @@ void server_callback(evutil_socket_t fd, short event, void *arg) {
auto msg = parse_dhcpv6_hdr(message_buffer);
counters[msg->msg_type]++;
update_counter(config->db, config->counterVlan, msg->msg_type);
std::string counterVlan = counter_table;
update_counter(config->table, counterVlan.append(config->interface), msg->msg_type);
if (msg->msg_type == DHCPv6_MESSAGE_TYPE_RELAY_REPL) {
relay_relay_reply(config->local_sock, message_buffer, data, config);
}
@ -673,17 +684,17 @@ void loop_relay(std::vector<relay_config> *vlans, swss::DBConnector *db) {
int index = if_nametoindex(ifname);
config.db = db;
config.counterVlan = "DHCPv6_COUNTER_TABLE|";
config.counterVlan.append(ifname);
initialize_counter(config.db, config.counterVlan);
std::string counterVlan = counter_table;
swss::Table table = swss::Table(config.db, counterVlan);
initialize_counter(&table, config.interface);
filter = sock_open(index, &ether_relay_fprog);
prepare_socket(&local_sock, &config, index);
prepare_socket(&local_sock);
sockets.push_back(filter);
sockets.push_back(local_sock);
prepare_relay_config(&config, local_sock, filter);
prepare_relay_config(&config, &local_sock, filter);
evutil_make_listen_socket_reuseable(filter);
evutil_make_socket_nonblocking(filter);

View File

@ -45,11 +45,11 @@ struct relay_config {
int filter;
sockaddr_in6 link_address;
swss::DBConnector *db;
swss::Table *table;
std::string interface;
std::vector<std::string> servers;
std::vector<sockaddr_in6> servers_sock;
bool is_option_79;
std::string counterVlan;
};
@ -91,7 +91,7 @@ struct linklayer_addr_option {
int sock_open(int ifindex, const struct sock_fprog *fprog);
/**
* @code prepare_socket(int *local_sock, arg_config *config);
* @code prepare_socket(int *local_sock);
*
* @brief prepare L3 socket for sending
*
@ -101,10 +101,10 @@ int sock_open(int ifindex, const struct sock_fprog *fprog);
*
* @return none
*/
void prepare_socket(int *local_sock, relay_config *config, int index);
void prepare_socket(int *local_sock);
/**
* @code prepare_relay_config(relay_config *interface_config, int local_sock, int filter);
* @code prepare_relay_config(relay_config *interface_config, int *local_sock, int filter);
*
* @brief prepare for specified relay interface config: server and link address
*
@ -114,7 +114,7 @@ void prepare_socket(int *local_sock, relay_config *config, int index);
*
* @return none
*/
void prepare_relay_config(relay_config *interface_config, int local_sock, int filter);
void prepare_relay_config(relay_config *interface_config, int *local_sock, int filter);
/**
* @code relay_forward(uint8_t *buffer, const struct dhcpv6_msg *msg, uint16_t msg_length);
@ -211,16 +211,16 @@ void signal_callback(evutil_socket_t fd, short event, void *arg);
void shutdown();
/**
* @code void initialize_counter(swss::DBConnector *db, std::string counterVlan);
* @code void initialize_counter(swss::Table *table, std::string counterVlan)
*
* @brief initialize the counter by each Vlan
*
* @param swss::DBConnector *db state_db connector
* @param swss::Table *table DHCPv6_COUNTER table
* @param counterVlan counter table with interface name
*
* @return none
*/
void initialize_counter(swss::DBConnector *db, std::string counterVlan);
void initialize_counter(swss::Table *table, std::string counterVlan);
/**
* @code void update_counter(swss::DBConnector *db, std::string CounterVlan, uint8_t msg_type);

View File

@ -18,6 +18,6 @@ C_DEPS += \
src/%.o: src/%.cpp
@echo 'Building file: $<'
@echo 'Invoking: GCC C++ Compiler'
$(CC) -std=c++17 -D__FILENAME__="$(subst src/,,$<)" $(LIBS) -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
$(CC) -std=c++14 -D__FILENAME__="$(subst src/,,$<)" $(LIBS) -Wall -c -fmessage-length=0 -fPIC -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
@echo 'Finished building: $<'
@echo ' '

View File

@ -120,6 +120,8 @@ static struct sock_fprog dhcp_sock_bfp = {
*/
static dhcp_device_context_t aggregate_dev = {0};
static dhcp_device_context_t *mgmt_intf = NULL;
/** Monitored DHCPv4 message type */
static dhcpv4_message_type_t v4_monitored_msgs[] = {
DHCPv4_MESSAGE_TYPE_DISCOVER,
@ -175,6 +177,11 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context,
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.v4counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
// If the packet recieved on the mgmt interface, we don't want to increment the aggregate device
if (context == mgmt_intf)
{
break;
}
aggregate_dev.counters.v4counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
}
break;
@ -185,6 +192,11 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context,
if ((context->giaddr_ip == iphdr->ip_dst.s_addr && context->is_uplink && dir == DHCP_RX) ||
(!context->is_uplink && dir == DHCP_TX)) {
context->counters.v4counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
// If the packet recieved on the mgmt interface, we don't want to increment the aggregate device
if (context == mgmt_intf)
{
break;
}
aggregate_dev.counters.v4counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++;
}
break;
@ -223,6 +235,11 @@ static void handle_dhcpv6_option(dhcp_device_context_t *context,
case DHCPv6_MESSAGE_TYPE_RECONFIGURE:
case DHCPv6_MESSAGE_TYPE_INFORMATION_REQUEST:
context->counters.v6counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option]++;
// If the packet recieved on the mgmt interface, we don't want to increment the aggregate device
if (context == mgmt_intf)
{
break;
}
aggregate_dev.counters.v6counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option]++;
break;
default:
@ -308,7 +325,7 @@ static void read_callback(int fd, short event, void *arg)
}
}
else if (!is_ipv4 && dhcpv6_enabled && (buffer_sz > UDPv6_START_OFFSET + sizeof(struct udphdr) + DHCPv6_TYPE_LENGTH)) {
const u_char* dhcp_option = context->buffer + dhcp_option_offset;
const u_char* dhcp_header = context->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] &&
@ -318,23 +335,25 @@ static void read_callback(int fd, short event, void *arg)
DHCP_TX : DHCP_RX;
int offset = 0;
uint16_t option = 0;
uint16_t current_option_len = 0;
// Get to inner DHCP header from encapsulated RELAY_FORWARD or RELAY_REPLY header
while (dhcp_option[offset] == DHCPv6_MESSAGE_TYPE_RELAY_FORWARD || dhcp_option[offset] == DHCPv6_MESSAGE_TYPE_RELAY_REPLY)
while (dhcp_header[offset] == DHCPv6_MESSAGE_TYPE_RELAY_FORWARD || dhcp_header[offset] == DHCPv6_MESSAGE_TYPE_RELAY_REPLY)
{
// Get to DHCPv6_OPTION_RELAY_MSG from all options
offset += DHCPv6_RELAY_MSG_OPTIONS_OFFSET;
option = htons(*((uint16_t*)(&(dhcp_option[offset]))));
option = htons(*((uint16_t*)(&(dhcp_header[offset]))));
while (option != DHCPv6_OPTION_RELAY_MSG)
{
offset += DHCPv6_OPTION_LENGTH;
// Add to offset the option length and get the next option ID
offset += htons(*((uint16_t*)(&(dhcp_option[offset]))));
option = htons(*((uint16_t*)(&(dhcp_option[offset]))));
current_option_len = htons(*((uint16_t*)(&(dhcp_header[offset + DHCPv6_OPTION_LENGTH]))));
offset += DHCPv6_OPTION_LENGTH + DHCPv6_OPTION_LEN_LENGTH + current_option_len;
option = htons(*((uint16_t*)(&(dhcp_header[offset]))));
}
// Set the offset to DHCP-relay-message data
offset += DHCPv6_OPTION_LENGTH + DHCPv6_OPTION_LEN_LENGTH;
}
handle_dhcpv6_option(context, dhcp_option[offset], dir);
handle_dhcpv6_option(context, dhcp_header[offset], dir);
} else {
syslog(LOG_WARNING, "read_callback(%s): read length (%ld) is too small to capture DHCP options",
context->intf, buffer_sz);
@ -553,7 +572,7 @@ static dhcp_mon_status_t dhcp_device_check_health(dhcp_mon_check_t check_type,
{
dhcp_mon_status_t rv = DHCP_MON_STATUS_HEALTHY;
if (dhcp_device_is_dhcp_inactive(aggregate_dev.counters.v4counters, aggregate_dev.counters.v6counters, type)) {
if (dhcp_device_is_dhcp_inactive(v4counters, v6counters, type)) {
rv = DHCP_MON_STATUS_INDETERMINATE;
} else if (check_type == DHCP_MON_CHECK_POSITIVE) {
rv = dhcp_device_check_positive_health(v4counters, v6counters, type);
@ -946,4 +965,14 @@ void dhcp_device_active_types(bool dhcpv4, bool dhcpv6)
{
dhcpv4_enabled = dhcpv4;
dhcpv6_enabled = dhcpv6;
}
}
/**
* @code dhcp_device_init_mgmt_intf(mgmt_intf_context);
*
* @brief assign context address of mgmt interface
*/
void dhcp_device_init_mgmt_intf(dhcp_device_context_t *mgmt_intf_context)
{
mgmt_intf = mgmt_intf_context;
}

View File

@ -255,4 +255,15 @@ void dhcp_device_print_status(dhcp_device_context_t *context, dhcp_counters_type
* @return none
*/
void dhcp_device_active_types(bool dhcpv4, bool dhcpv6);
/**
* @code dhcp_device_init_mgmt_intf(mgmt_intf_context);
*
* @brief assign context address of mgmt interface
*
* @param mgmt_intf_context MGMT interface context struct address
*
* @return none
*/
void dhcp_device_init_mgmt_intf(dhcp_device_context_t *mgmt_intf_context);
#endif /* DHCP_DEVICE_H_ */

View File

@ -148,6 +148,9 @@ int dhcp_devman_add_intf(const char *name, char intf_type)
strncpy(agg_dev->intf + sizeof(AGG_DEV_PREFIX) - 1, name, sizeof(agg_dev->intf) - sizeof(AGG_DEV_PREFIX));
agg_dev->intf[sizeof(agg_dev->intf) - 1] = '\0';
}
else if (rv == 0 && intf_type == 'm') {
dhcp_device_init_mgmt_intf(dev->dev_context);
}
LIST_INSERT_HEAD(&intfs, dev, entry);
}
@ -282,4 +285,4 @@ void dhcp_devman_print_status(dhcp_device_context_t *context, dhcp_counters_type
void dhcp_devman_active_types(bool dhcpv4, bool dhcpv6)
{
dhcp_device_active_types(dhcpv4, dhcpv6);
}
}

View File

@ -194,4 +194,4 @@ int main(int argc, char **argv)
closelog();
return rv;
}
}

View File

@ -19,8 +19,8 @@ autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[group:isc-dhcp-relay]
programs=isc-dhcp-relayv4-Vlan1000,isc-dhcpv6-relay-Vlan1000
[group:dhcp-relay]
programs=isc-dhcpv4-relay-Vlan1000,dhcp6relay
[program:isc-dhcpv4-relay-Vlan1000]
command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id Vlan1000 -iu PortChannel01 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04 192.0.0.1 192.0.0.2
@ -30,8 +30,9 @@ autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:isc-dhcpv6-relay-Vlan1000]
command=/usr/sbin/dhcrelay -d -6 --name-alias-map-file /tmp/port-name-alias-map.txt -l Vlan1000 -iu PortChannel01 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04
[program:dhcp6relay]
command=/usr/sbin/dhcp6relay
priority=3
autostart=false
autorestart=false
@ -51,3 +52,4 @@ stdout_logfile=syslog
stderr_logfile=syslog

View File

@ -342,4 +342,4 @@ class TestCfgGen(TestCase):
output.strip(),
"{'Vlan1000': {'dhcpv6_servers': ['fc02:2000::1', 'fc02:2000::2']}}"
)