libvma/0001-Issue-4223310-VMA-support-for-kernel-6.10.patch
Mohammad Heib 795b55d53b Add support for kernel 6.10.
Resolves: RHEL-24810
Signed-off-by: Mohammad Heib <mheib@redhat.com>
2025-01-06 15:22:00 +02:00

2132 lines
72 KiB
Diff

From 0389fdac1dd022e93cb332b7b527a576fc8b064f Mon Sep 17 00:00:00 2001
From: Tomer Cabouly <tcabouly@nvidia.com>
Date: Tue, 17 Dec 2024 14:57:33 +0200
Subject: [PATCH] issue: 4223310 VMA support for kernel 6.10
Kernel 6.10 netlink has breaked VMA functionality.
Transitioned to libnl - an abstraction that wraps netlink.
Signed-off-by: Tomer Cabouly <tcabouly@nvidia.com>
---
src/vma/proto/netlink_socket_mgr.h | 326 ++++--------
src/vma/proto/route_table_mgr.cpp | 823 +++++++++++++++--------------
src/vma/proto/route_table_mgr.h | 66 ++-
src/vma/proto/rule_table_mgr.cpp | 341 ++++++------
src/vma/proto/rule_table_mgr.h | 36 +-
src/vma/proto/rule_val.cpp | 106 ++--
src/vma/proto/rule_val.h | 83 ++-
7 files changed, 854 insertions(+), 927 deletions(-)
diff --git a/src/vma/proto/netlink_socket_mgr.h b/src/vma/proto/netlink_socket_mgr.h
index 1e1c978c2..dbe1b545c 100644
--- a/src/vma/proto/netlink_socket_mgr.h
+++ b/src/vma/proto/netlink_socket_mgr.h
@@ -30,10 +30,10 @@
* SOFTWARE.
*/
-
#ifndef NETLINK_SOCKET_MGR_H
#define NETLINK_SOCKET_MGR_H
+#include <cstddef>
#include <unistd.h>
#include <bits/sockaddr.h>
#include <stdio.h>
@@ -48,6 +48,11 @@
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <fcntl.h>
+#include <netlink/netlink.h>
+#include <netlink/msg.h>
+#include <netlink/route/route.h>
+#include <netlink/route/rule.h>
+#include <netlink/route/link.h>
#include "utils/bullseye.h"
#include "utils/lock_wrapper.h"
@@ -60,261 +65,164 @@
#include "vma/sock/socket_fd_api.h"
#include "vma/sock/sock-redirect.h"
-
#ifndef MODULE_NAME
-#define MODULE_NAME "netlink_socket_mgr:"
+#define MODULE_NAME "netlink_socket_mgr:"
#endif
-#define NLMSG_TAIL(nmsg) ((struct rtattr *) (((uint8_t *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+#define NLMSG_TAIL(nmsg) ((struct rtattr *)(((uint8_t *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
#define MAX_TABLE_SIZE 4096
-#define MSG_BUFF_SIZE 81920
+#define MSG_BUFF_SIZE 81920
// This enum specify the type of data to be retrieve using netlink socket.
-enum nl_data_t
-{
- RULE_DATA_TYPE,
- ROUTE_DATA_TYPE
-};
+enum nl_data_t { RULE_DATA_TYPE, ROUTE_DATA_TYPE };
/*
-* This class manage retrieving data (Rule, Route) from kernel using netlink socket.
-*/
-template <typename Type>
-class netlink_socket_mgr
-{
+ * This class manage retrieving data (Rule, Route) from kernel using netlink socket.
+ */
+template <typename Type> class netlink_socket_mgr {
public:
- netlink_socket_mgr(nl_data_t data_type);
- virtual ~netlink_socket_mgr();
-
-protected:
- typedef struct
- {
- Type value[MAX_TABLE_SIZE];
- uint16_t entries_num;
- } table_t;
-
- table_t m_tab;
-
- virtual bool parse_enrty(nlmsghdr *nl_header, Type *p_val) = 0;
- virtual void update_tbl();
- virtual void print_val_tbl();
-
- void build_request(struct nlmsghdr **nl_msg);
- bool query(struct nlmsghdr *&nl_msg, int &len);
- int recv_info();
- void parse_tbl(int len, int *p_ent_num = NULL);
-
+ netlink_socket_mgr(nl_data_t data_type);
+ virtual ~netlink_socket_mgr();
+
+protected:
+ typedef struct {
+ Type value[MAX_TABLE_SIZE];
+ uint16_t entries_num;
+ } table_t;
+
+ table_t m_tab;
+
+ virtual bool parse_entry(struct nl_object *nl_obj, void *p_val_context) = 0;
+ virtual void update_tbl();
+ virtual void print_val_tbl();
+
+ void build_request(struct nlmsghdr **nl_msg);
+ bool query(struct nlmsghdr *&nl_msg, int &len);
+ int recv_info();
+ void parse_tbl_from_latest_cache(struct nl_cache *cache_state);
+
private:
- nl_data_t m_data_type;
+ nl_data_t m_data_type;
- int m_fd; // netlink socket to communicate with the kernel
- uint32_t m_pid; // process pid
- uint32_t m_seq_num; // seq num of the netlink messages
- char m_msg_buf[MSG_BUFF_SIZE]; // we use this buffer for sending/receiving netlink messages
- uint32_t m_buff_size;
+ nl_sock *m_sock; // netlink socket to communicate with the kernel
+ uint32_t m_pid; // process pid
+ uint32_t m_seq_num; // seq num of the netlink messages
+ char m_msg_buf[MSG_BUFF_SIZE]; // we use this buffer for sending/receiving netlink messages
+ uint32_t m_buff_size;
};
/*********************************Implementation ********************************/
-template <typename Type>
-netlink_socket_mgr <Type>::netlink_socket_mgr(nl_data_t data_type)
+template <typename Type> netlink_socket_mgr<Type>::netlink_socket_mgr(nl_data_t data_type)
{
- __log_dbg("");
-
- m_data_type = data_type;
- m_pid = getpid();
- m_buff_size = MSG_BUFF_SIZE;
- m_seq_num = 0;
+ __log_dbg("");
- memset(m_msg_buf, 0, m_buff_size);
+ m_data_type = data_type;
+ m_pid = getpid();
+ m_buff_size = MSG_BUFF_SIZE;
+ m_seq_num = 0;
- // Create Socket
- BULLSEYE_EXCLUDE_BLOCK_START
- if ((m_fd = orig_os_api.socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) {
- __log_err("NL socket Creation: ");
- return;
- }
+ memset(m_msg_buf, 0, m_buff_size);
- if (orig_os_api.fcntl(m_fd, F_SETFD, FD_CLOEXEC) != 0) {
- __log_warn("Fail in fctl, error = %d", errno);
- }
- BULLSEYE_EXCLUDE_BLOCK_END
+ // Create Socket
- __log_dbg("Done");
-}
+ BULLSEYE_EXCLUDE_BLOCK_START
+ m_sock = nl_socket_alloc();
+ if (m_sock == nullptr) {
+ __log_err("NL socket Creation: ");
+ return;
+ }
-template <typename Type>
-netlink_socket_mgr <Type>::~netlink_socket_mgr()
-{
- __log_dbg("");
- if (m_fd) {
- orig_os_api.close(m_fd);
- m_fd = -1;
- }
-
- __log_dbg("Done");
-}
+ if (nl_connect(m_sock, NETLINK_ROUTE) < 0) {
+ __log_err("NL socket Connection: ");
+ nl_socket_free(m_sock);
+ m_sock = nullptr;
+ return;
+ }
-// This function build Netlink request to retrieve data (Rule, Route) from kernel.
-// Parameters :
-// nl_msg : request to be returned
-template <typename Type>
-void netlink_socket_mgr <Type>::build_request(struct nlmsghdr **nl_msg)
-{
- struct rtmsg *rt_msg;
-
- memset(m_msg_buf, 0, m_buff_size);
-
- // point the header and the msg structure pointers into the buffer
- *nl_msg = (struct nlmsghdr *)m_msg_buf;
- rt_msg = (struct rtmsg *)NLMSG_DATA(*nl_msg);
-
- //Fill in the nlmsg header
- (*nl_msg)->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- (*nl_msg)->nlmsg_seq = m_seq_num++;
- (*nl_msg)->nlmsg_pid = m_pid;
- rt_msg->rtm_family = AF_INET;
-
- if (m_data_type == RULE_DATA_TYPE)
- {
- (*nl_msg)->nlmsg_type = RTM_GETRULE;
- }
- else if (m_data_type == ROUTE_DATA_TYPE)
- {
- (*nl_msg)->nlmsg_type = RTM_GETROUTE;
- }
-
- (*nl_msg)->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+ BULLSEYE_EXCLUDE_BLOCK_END
+ __log_dbg("Done");
}
-// Query built request and receive requested data (Rule, Route)
-// Parameters:
-// nl_msg : request that is built previously.
-// len : length of received data.
-template <typename Type>
-bool netlink_socket_mgr <Type>::query(struct nlmsghdr *&nl_msg, int &len)
+template <typename Type> netlink_socket_mgr<Type>::~netlink_socket_mgr()
{
- if(m_fd < 0)
- return false;
-
- BULLSEYE_EXCLUDE_BLOCK_START
- if(orig_os_api.send(m_fd, nl_msg, nl_msg->nlmsg_len, 0) < 0){
- __log_err("Write To Socket Failed...\n");
- return false;
- }
- if((len = recv_info()) < 0) {
- __log_err("Read From Socket Failed...\n");
- return false;
- }
- BULLSEYE_EXCLUDE_BLOCK_END
-
- return true;
-}
+ __log_dbg("");
+ if (m_sock != nullptr) {
+ nl_socket_free(m_sock);
+ m_sock = nullptr;
+ }
-// Receive requested data and save it locally.
-// Return length of received data.
-template <typename Type>
-int netlink_socket_mgr <Type>::recv_info()
-{
- struct nlmsghdr *nlHdr;
- int readLen = 0, msgLen = 0;
-
- char *buf_ptr = m_msg_buf;
-
- do{
- //Receive response from the kernel
- BULLSEYE_EXCLUDE_BLOCK_START
- if((readLen = orig_os_api.recv(m_fd, buf_ptr, MSG_BUFF_SIZE - msgLen, 0)) < 0){
- __log_err("SOCK READ: ");
- return -1;
- }
-
- nlHdr = (struct nlmsghdr *)buf_ptr;
-
- //Check if the header is valid
- if((NLMSG_OK(nlHdr, (u_int)readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR))
- {
- __log_err("Error in received packet, readLen = %d, msgLen = %d, type=%d, bufLen = %d", readLen, nlHdr->nlmsg_len, nlHdr->nlmsg_type, MSG_BUFF_SIZE);
- if (nlHdr->nlmsg_len == MSG_BUFF_SIZE) {
- __log_err("The buffer we pass to netlink is too small for reading the whole table");
- }
- return -1;
- }
- BULLSEYE_EXCLUDE_BLOCK_END
-
- buf_ptr += readLen;
- msgLen += readLen;
-
- //Check if the its the last message
- if(nlHdr->nlmsg_type == NLMSG_DONE ||
- (nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) {
- break;
- }
-
- } while((nlHdr->nlmsg_seq != m_seq_num) || (nlHdr->nlmsg_pid != m_pid));
- return msgLen;
+ __log_dbg("Done");
}
// Update data in a table
-template <typename Type>
-void netlink_socket_mgr <Type>::update_tbl()
+template <typename Type> void netlink_socket_mgr<Type>::update_tbl()
{
- struct nlmsghdr *nl_msg = NULL;
- int counter = 0;
- int len = 0;
+ m_tab.entries_num = 0;
- m_tab.entries_num = 0;
+ struct nl_cache *cache_state = {0};
+ int err = 0;
- // Build Netlink request to get route entry
- build_request(&nl_msg);
+ // cache allocation fetches the latest existing rules/routes
+ if (m_data_type == RULE_DATA_TYPE) {
+ err = rtnl_rule_alloc_cache(m_sock, AF_INET, &cache_state);
+ } else if (m_data_type == ROUTE_DATA_TYPE) {
+ err = rtnl_route_alloc_cache(m_sock, AF_INET, 0, &cache_state);
+ }
- // Query built request and receive requested data
- if (!query(nl_msg, len))
- return;
+ if (err < 0) {
+ throw_vma_exception("Failed to allocate route cache");
+ }
- // Parse received data in custom object (route_val)
- parse_tbl(len, &counter);
-
- m_tab.entries_num = counter;
-
- if (counter >= MAX_TABLE_SIZE) {
- __log_warn("reached the maximum route table size");
- }
+ // Parse received data in custom object (route_val)
+ parse_tbl_from_latest_cache(cache_state);
}
// Parse received data in a table
-// Parameters:
+// Parameters:
// len : length of received data.
// p_ent_num : number of rows in received data.
template <typename Type>
-void netlink_socket_mgr <Type>::parse_tbl(int len, int *p_ent_num)
+void netlink_socket_mgr<Type>::parse_tbl_from_latest_cache(struct nl_cache *cache_state)
{
- struct nlmsghdr *nl_header;
- int entry_cnt = 0;
-
- nl_header = (struct nlmsghdr *) m_msg_buf;
- for(;NLMSG_OK(nl_header, (u_int)len) && entry_cnt < MAX_TABLE_SIZE; nl_header = NLMSG_NEXT(nl_header, len))
- {
- if (parse_enrty(nl_header, &m_tab.value[entry_cnt])) {
- entry_cnt++;
- }
- }
- if (p_ent_num)
- *p_ent_num = entry_cnt;
+ uint16_t entry_cnt = 0;
+
+ struct nl_iterator_context {
+ Type *p_val_array;
+ uint16_t &entry_cnt;
+ netlink_socket_mgr<Type> *this_ptr;
+ } iterator_context = {m_tab.value, entry_cnt, this};
+
+ // a lambda can't be casted to a c-fptr with ref captures - so we provide context ourselves
+ nl_cache_foreach(
+ cache_state,
+ [](struct nl_object *nl_obj, void *context) {
+ nl_iterator_context *operation_context =
+ reinterpret_cast<nl_iterator_context *>(context);
+ const bool is_valid_entry = operation_context->this_ptr->parse_entry(
+ nl_obj, operation_context->p_val_array + operation_context->entry_cnt);
+ if (is_valid_entry) {
+ ++operation_context->entry_cnt;
+ }
+ },
+ &iterator_context);
+
+ m_tab.entries_num = entry_cnt;
+ if (m_tab.entries_num >= MAX_TABLE_SIZE) {
+ __log_warn("reached the maximum route table size");
+ }
}
//print the table
-template <typename Type>
-void netlink_socket_mgr <Type>::print_val_tbl()
+template <typename Type> void netlink_socket_mgr<Type>::print_val_tbl()
{
- Type *p_val;
- for (int i = 0; i < m_tab.entries_num; i++)
- {
- p_val = &m_tab.value[i];
- p_val->print_val();
- }
+ Type *p_val;
+ for (int i = 0; i < m_tab.entries_num; i++) {
+ p_val = &m_tab.value[i];
+ p_val->print_val();
+ }
}
#undef MODULE_NAME
diff --git a/src/vma/proto/route_table_mgr.cpp b/src/vma/proto/route_table_mgr.cpp
index 597d6343a..813772e74 100644
--- a/src/vma/proto/route_table_mgr.cpp
+++ b/src/vma/proto/route_table_mgr.cpp
@@ -30,7 +30,6 @@
* SOFTWARE.
*/
-
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -55,454 +54,470 @@
#include "ip_address.h"
// debugging macros
-#define MODULE_NAME "rtm:"
-#define rt_mgr_if_logpanic __log_panic
-#define rt_mgr_logerr __log_err
-#define rt_mgr_logwarn __log_warn
-#define rt_mgr_loginfo __log_info
-#define rt_mgr_logdbg __log_dbg
-#define rt_mgr_logfunc __log_func
-#define rt_mgr_logfuncall __log_funcall
-
-route_table_mgr* g_p_route_table_mgr = NULL;
-
-route_table_mgr::route_table_mgr() : netlink_socket_mgr<route_val>(ROUTE_DATA_TYPE), cache_table_mgr<route_rule_table_key, route_val*>("route_table_mgr")
+#define MODULE_NAME "rtm:"
+#define rt_mgr_if_logpanic __log_panic
+#define rt_mgr_logerr __log_err
+#define rt_mgr_logwarn __log_warn
+#define rt_mgr_loginfo __log_info
+#define rt_mgr_logdbg __log_dbg
+#define rt_mgr_logfunc __log_func
+#define rt_mgr_logfuncall __log_funcall
+
+route_table_mgr *g_p_route_table_mgr = NULL;
+
+route_table_mgr::route_table_mgr()
+ : netlink_socket_mgr<route_val>(ROUTE_DATA_TYPE)
+ , cache_table_mgr<route_rule_table_key, route_val *>("route_table_mgr")
{
- rt_mgr_logdbg("");
-
- //Read Route table from kernel and save it in local variable.
- update_tbl();
-
- // create route_entry for each net_dev- needed for receiving port up/down events for net_dev_entry
- route_val *p_val;
- for (int i = 0; i < m_tab.entries_num; i++)
- {
- p_val = &m_tab.value[i];
- in_addr_t src_addr = p_val->get_src_addr();
- in_addr_route_entry_map_t::iterator iter = m_rte_list_for_each_net_dev.find(src_addr);
- // if src_addr of interface exists in the map, no need to create another route_entry
- if (iter == m_rte_list_for_each_net_dev.end()) {
- in_addr_t dst_ip = src_addr;
- in_addr_t src_ip = 0;
- uint8_t tos = 0;
- m_rte_list_for_each_net_dev[src_addr] = create_new_entry(route_rule_table_key(dst_ip, src_ip, tos), NULL);
- }
- }
-
- //Print table
- print_val_tbl();
-
- // register to netlink event
- g_p_netlink_handler->register_event(nlgrpROUTE, this);
- rt_mgr_logdbg("Registered to g_p_netlink_handler");
-
- rt_mgr_logdbg("Done");
+ rt_mgr_logdbg("");
+
+ //Read Route table from kernel and save it in local variable.
+ update_tbl();
+
+ // create route_entry for each net_dev- needed for receiving port up/down events for
+ // net_dev_entry
+ route_val *p_val;
+ for (int i = 0; i < m_tab.entries_num; i++) {
+ p_val = &m_tab.value[i];
+ in_addr_t src_addr = p_val->get_src_addr();
+ in_addr_route_entry_map_t::iterator iter = m_rte_list_for_each_net_dev.find(src_addr);
+ // if src_addr of interface exists in the map, no need to create another route_entry
+ if (iter == m_rte_list_for_each_net_dev.end()) {
+ in_addr_t dst_ip = src_addr;
+ in_addr_t src_ip = 0;
+ uint8_t tos = 0;
+ m_rte_list_for_each_net_dev[src_addr] =
+ create_new_entry(route_rule_table_key(dst_ip, src_ip, tos), NULL);
+ }
+ }
+
+ //Print table
+ print_val_tbl();
+
+ // register to netlink event
+ g_p_netlink_handler->register_event(nlgrpROUTE, this);
+ rt_mgr_logdbg("Registered to g_p_netlink_handler");
+
+ rt_mgr_logdbg("Done");
}
route_table_mgr::~route_table_mgr()
{
- rt_mgr_logdbg("");
-
- // clear all route_entrys created in the constructor
- in_addr_route_entry_map_t::iterator iter;
-
- while ((iter = m_rte_list_for_each_net_dev.begin()) != m_rte_list_for_each_net_dev.end()) {
- delete(iter->second);
- m_rte_list_for_each_net_dev.erase(iter);
- }
-
- rt_tbl_cach_entry_map_t::iterator cache_itr;
- while ((cache_itr = m_cache_tbl.begin()) != m_cache_tbl.end()) {
- delete(cache_itr->second);
- m_cache_tbl.erase(cache_itr);
- }
- rt_mgr_logdbg("Done");
+ rt_mgr_logdbg("");
+
+ // clear all route_entrys created in the constructor
+ in_addr_route_entry_map_t::iterator iter;
+
+ while ((iter = m_rte_list_for_each_net_dev.begin()) != m_rte_list_for_each_net_dev.end()) {
+ delete (iter->second);
+ m_rte_list_for_each_net_dev.erase(iter);
+ }
+
+ rt_tbl_cach_entry_map_t::iterator cache_itr;
+ while ((cache_itr = m_cache_tbl.begin()) != m_cache_tbl.end()) {
+ delete (cache_itr->second);
+ m_cache_tbl.erase(cache_itr);
+ }
+ rt_mgr_logdbg("Done");
}
void route_table_mgr::update_tbl()
{
- auto_unlocker lock(m_lock);
+ auto_unlocker lock(m_lock);
- netlink_socket_mgr<route_val>::update_tbl();
+ netlink_socket_mgr<route_val>::update_tbl();
- rt_mgr_update_source_ip();
+ rt_mgr_update_source_ip();
- return;
+ return;
}
void route_table_mgr::rt_mgr_update_source_ip()
{
- route_val *p_val;
- //for route entries which still have no src ip and no gw
- for (int i = 0; i < m_tab.entries_num; i++) {
- p_val = &m_tab.value[i];
- if (p_val->get_src_addr() || p_val->get_gw_addr()) continue;
- if (g_p_net_device_table_mgr) { //try to get src ip from net_dev list of the interface
- in_addr_t longest_prefix = 0;
- in_addr_t correct_src = 0;
- local_ip_list_t::iterator lip_iter;
- local_ip_list_t lip_offloaded_list = g_p_net_device_table_mgr->get_ip_list(p_val->get_if_index());
- if (!lip_offloaded_list.empty()) {
- for (lip_iter = lip_offloaded_list.begin(); lip_offloaded_list.end() != lip_iter; lip_iter++)
- {
- ip_data_t ip = *lip_iter;
- if((p_val->get_dst_addr() & ip.netmask) == (ip.local_addr & ip.netmask)) { //found a match in routing table
- if((ip.netmask | longest_prefix) != longest_prefix){
- longest_prefix = ip.netmask; // this is the longest prefix match
- correct_src = ip.local_addr;
- }
- }
- }
- if (correct_src) {
- p_val->set_src_addr(correct_src);
- continue;
- }
- }
- }
- // if still no src ip, get it from ioctl
- struct sockaddr_in src_addr;
- char *if_name = (char *)p_val->get_if_name();
- if (!get_ipv4_from_ifname(if_name, &src_addr)) {
- p_val->set_src_addr(src_addr.sin_addr.s_addr);
- }
- else {
- // Failed mapping if_name to IPv4 address
- rt_mgr_logwarn("could not figure out source ip for rtv = %s", p_val->to_str());
- }
- }
-
- //for route entries with gateway, do recursive search for src ip
- int num_unresolved_src = m_tab.entries_num;
- int prev_num_unresolved_src = 0;
- do {
- prev_num_unresolved_src = num_unresolved_src;
- num_unresolved_src = 0;
- for (int i = 0; i < m_tab.entries_num; i++) {
- p_val = &m_tab.value[i];
- if (p_val->get_gw_addr() && !p_val->get_src_addr()) {
- route_val* p_val_dst;
- in_addr_t in_addr = p_val->get_gw_addr();
- uint32_t table_id = p_val->get_table_id();
- if (find_route_val(in_addr, table_id, p_val_dst)) {
- if (p_val_dst->get_src_addr()) {
- p_val->set_src_addr(p_val_dst->get_src_addr());
- } else if (p_val == p_val_dst) { //gateway of the entry lead to same entry
- local_ip_list_t::iterator lip_iter;
- local_ip_list_t lip_offloaded_list = g_p_net_device_table_mgr->get_ip_list(p_val->get_if_index());
- for (lip_iter = lip_offloaded_list.begin(); lip_offloaded_list.end() != lip_iter; lip_iter++)
- {
- ip_data_t ip = *lip_iter;
- if(p_val->get_gw_addr() == ip.local_addr) {
- p_val->set_gw(0);
- p_val->set_src_addr(ip.local_addr);
- break;
- }
- }
- if (!p_val->get_src_addr())
- num_unresolved_src++;
- } else {
- num_unresolved_src++;
- }
- // gateway and source are equal, no need of gw.
- if (p_val->get_src_addr() == p_val->get_gw_addr()) {
- p_val->set_gw(0);
- }
- } else {
- num_unresolved_src++;
- }
- }
- }
- } while (num_unresolved_src && prev_num_unresolved_src > num_unresolved_src);
-
- //for route entries which still have no src ip
- for (int i = 0; i < m_tab.entries_num; i++) {
- p_val = &m_tab.value[i];
- if (p_val->get_src_addr()) continue;
- if (p_val->get_gw_addr()) {
- rt_mgr_logdbg("could not figure out source ip for gw address. rtv = %s", p_val->to_str());
- }
- // if still no src ip, get it from ioctl
- struct sockaddr_in src_addr;
- char *if_name = (char *)p_val->get_if_name();
- if (!get_ipv4_from_ifname(if_name, &src_addr)) {
- p_val->set_src_addr(src_addr.sin_addr.s_addr);
- }
- else {
- // Failed mapping if_name to IPv4 address
- rt_mgr_logdbg("could not figure out source ip for rtv = %s", p_val->to_str());
- }
- }
+ route_val *p_val;
+ //for route entries which still have no src ip and no gw
+ for (int i = 0; i < m_tab.entries_num; i++) {
+ p_val = &m_tab.value[i];
+ if (p_val->get_src_addr() || p_val->get_gw_addr()) {
+ continue;
+ }
+ if (g_p_net_device_table_mgr) { //try to get src ip from net_dev list of the interface
+ in_addr_t longest_prefix = 0;
+ in_addr_t correct_src = 0;
+ local_ip_list_t::iterator lip_iter;
+ local_ip_list_t lip_offloaded_list =
+ g_p_net_device_table_mgr->get_ip_list(p_val->get_if_index());
+ if (!lip_offloaded_list.empty()) {
+ for (lip_iter = lip_offloaded_list.begin(); lip_offloaded_list.end() != lip_iter;
+ lip_iter++) {
+ ip_data_t ip = *lip_iter;
+ if ((p_val->get_dst_addr() & ip.netmask) ==
+ (ip.local_addr & ip.netmask)) { //found a match in routing table
+ if ((ip.netmask | longest_prefix) != longest_prefix) {
+ longest_prefix = ip.netmask; // this is the longest prefix match
+ correct_src = ip.local_addr;
+ }
+ }
+ }
+ if (correct_src) {
+ p_val->set_src_addr(correct_src);
+ continue;
+ }
+ }
+ }
+ // if still no src ip, get it from ioctl
+ struct sockaddr_in src_addr;
+ char *if_name = (char *)p_val->get_if_name();
+ if (!get_ipv4_from_ifname(if_name, &src_addr)) {
+ p_val->set_src_addr(src_addr.sin_addr.s_addr);
+ } else {
+ // Failed mapping if_name to IPv4 address
+ rt_mgr_logwarn("could not figure out source ip for rtv = %s", p_val->to_str());
+ }
+ }
+
+ //for route entries with gateway, do recursive search for src ip
+ int num_unresolved_src = m_tab.entries_num;
+ int prev_num_unresolved_src = 0;
+ do {
+ prev_num_unresolved_src = num_unresolved_src;
+ num_unresolved_src = 0;
+ for (int i = 0; i < m_tab.entries_num; i++) {
+ p_val = &m_tab.value[i];
+ if (p_val->get_gw_addr() && !p_val->get_src_addr()) {
+ route_val *p_val_dst;
+ in_addr_t in_addr = p_val->get_gw_addr();
+ uint32_t table_id = p_val->get_table_id();
+ if (find_route_val(in_addr, table_id, p_val_dst)) {
+ if (p_val_dst->get_src_addr()) {
+ p_val->set_src_addr(p_val_dst->get_src_addr());
+ } else if (p_val == p_val_dst) { //gateway of the entry lead to same entry
+ local_ip_list_t::iterator lip_iter;
+ local_ip_list_t lip_offloaded_list =
+ g_p_net_device_table_mgr->get_ip_list(p_val->get_if_index());
+ for (lip_iter = lip_offloaded_list.begin();
+ lip_offloaded_list.end() != lip_iter; lip_iter++) {
+ ip_data_t ip = *lip_iter;
+ if (p_val->get_gw_addr() == ip.local_addr) {
+ p_val->set_gw(0);
+ p_val->set_src_addr(ip.local_addr);
+ break;
+ }
+ }
+ if (!p_val->get_src_addr()) {
+ num_unresolved_src++;
+ }
+ } else {
+ num_unresolved_src++;
+ }
+ // gateway and source are equal, no need of gw.
+ if (p_val->get_src_addr() == p_val->get_gw_addr()) {
+ p_val->set_gw(0);
+ }
+ } else {
+ num_unresolved_src++;
+ }
+ }
+ }
+ } while (num_unresolved_src && prev_num_unresolved_src > num_unresolved_src);
+
+ //for route entries which still have no src ip
+ for (int i = 0; i < m_tab.entries_num; i++) {
+ p_val = &m_tab.value[i];
+ if (p_val->get_src_addr()) {
+ continue;
+ }
+ if (p_val->get_gw_addr()) {
+ rt_mgr_logdbg("could not figure out source ip for gw address. rtv = %s",
+ p_val->to_str());
+ }
+ // if still no src ip, get it from ioctl
+ struct sockaddr_in src_addr;
+ char *if_name = (char *)p_val->get_if_name();
+ if (!get_ipv4_from_ifname(if_name, &src_addr)) {
+ p_val->set_src_addr(src_addr.sin_addr.s_addr);
+ } else {
+ // Failed mapping if_name to IPv4 address
+ rt_mgr_logdbg("could not figure out source ip for rtv = %s", p_val->to_str());
+ }
+ }
}
-bool route_table_mgr::parse_enrty(nlmsghdr *nl_header, route_val *p_val)
+bool route_table_mgr::parse_entry(struct nl_object *nl_obj, void *p_val_context)
{
- int len;
- struct rtmsg *rt_msg;
- struct rtattr *rt_attribute;
-
- // get route entry header
- rt_msg = (struct rtmsg *) NLMSG_DATA(nl_header);
-
- // we are not concerned about the local and default route table
- if (rt_msg->rtm_family != AF_INET || rt_msg->rtm_table == RT_TABLE_LOCAL)
- return false;
-
- p_val->set_protocol(rt_msg->rtm_protocol);
- p_val->set_scope(rt_msg->rtm_scope);
- p_val->set_type(rt_msg->rtm_type);
- p_val->set_table_id(rt_msg->rtm_table);
-
- in_addr_t dst_mask = htonl(VMA_NETMASK(rt_msg->rtm_dst_len));
- p_val->set_dst_mask(dst_mask);
- p_val->set_dst_pref_len(rt_msg->rtm_dst_len);
-
- len = RTM_PAYLOAD(nl_header);
- rt_attribute = (struct rtattr *) RTM_RTA(rt_msg);
-
- for (;RTA_OK(rt_attribute, len);rt_attribute=RTA_NEXT(rt_attribute,len)) {
- parse_attr(rt_attribute, p_val);
- }
- p_val->set_state(true);
- p_val->set_str();
- return true;
+ route_val *p_val = static_cast<route_val *>(p_val_context);
+ // Cast the generic nl_object to a specific route or rule object
+ struct rtnl_route *route = reinterpret_cast<struct rtnl_route *>(nl_obj);
+
+ // we are not concerned about the local and default route table
+ if (rtnl_route_get_family(route) != AF_INET || rtnl_route_get_table(route) == RT_TABLE_LOCAL) {
+ return false;
+ }
+
+ // Set protocol, scope, type, and table ID using libnl functions
+ p_val->set_protocol(rtnl_route_get_protocol(route));
+ p_val->set_scope(rtnl_route_get_scope(route));
+ p_val->set_type(rtnl_route_get_type(route));
+ p_val->set_table_id(rtnl_route_get_table(route));
+
+ // Set destination mask and prefix length
+ struct nl_addr *dst = rtnl_route_get_dst(route);
+ if (dst != nullptr) {
+ in_addr_t dst_mask = htonl(VMA_NETMASK(nl_addr_get_prefixlen(dst)));
+ p_val->set_dst_mask(dst_mask);
+ p_val->set_dst_pref_len(nl_addr_get_prefixlen(dst));
+ }
+
+ parse_attr(route, p_val);
+
+ p_val->set_state(true);
+ p_val->set_str();
+ return true;
}
-void route_table_mgr::parse_attr(struct rtattr *rt_attribute, route_val *p_val)
+void route_table_mgr::parse_attr(struct rtnl_route *route, route_val *p_val)
{
- switch (rt_attribute->rta_type) {
- case RTA_DST:
- p_val->set_dst_addr(*(in_addr_t *)RTA_DATA(rt_attribute));
- break;
- // next hop IPv4 address
- case RTA_GATEWAY:
- p_val->set_gw(*(in_addr_t *)RTA_DATA(rt_attribute));
- break;
- // unique ID associated with the network interface
- case RTA_OIF:
- p_val->set_if_index(*(int *)RTA_DATA(rt_attribute));
- char if_name[IFNAMSIZ];
- if_indextoname(p_val->get_if_index(),if_name);
- p_val->set_if_name(if_name);
- break;
- case RTA_SRC:
- case RTA_PREFSRC:
- p_val->set_src_addr(*(in_addr_t *)RTA_DATA(rt_attribute));
- break;
- case RTA_TABLE:
- p_val->set_table_id(*(uint32_t *)RTA_DATA(rt_attribute));
- break;
- case RTA_METRICS:
- {
- struct rtattr *rta = (struct rtattr *)RTA_DATA(rt_attribute);
- int len = RTA_PAYLOAD(rt_attribute);
- uint16_t type;
- while (RTA_OK(rta, len)) {
- type = rta->rta_type;
- switch (type) {
- case RTAX_MTU:
- p_val->set_mtu(*(uint32_t *)RTA_DATA(rta));
- break;
- default:
- rt_mgr_logdbg("got unexpected METRICS %d %x",
- type, *(uint32_t *)RTA_DATA(rta));
- break;
- }
- rta = RTA_NEXT(rta, len);
- }
- break;
- }
- default:
- rt_mgr_logdbg("got unexpected type %d %x", rt_attribute->rta_type,
- *(uint32_t *)RTA_DATA(rt_attribute));
- break;
- }
+ struct nl_addr *addr;
+
+ // Destination Address
+ addr = rtnl_route_get_dst(route);
+ if (addr) {
+ p_val->set_dst_addr(*(in_addr_t *)nl_addr_get_binary_addr(addr));
+ }
+
+ // Gateway Address (Next Hop)
+ struct rtnl_nexthop *nh = rtnl_route_nexthop_n(route, 0); // Assuming the first nexthop
+ if (nh) {
+ addr = rtnl_route_nh_get_gateway(nh);
+ if (addr) {
+ p_val->set_gw(*(in_addr_t *)nl_addr_get_binary_addr(addr));
+ }
+ }
+
+ // Output Interface Index and Name
+ const int if_index = rtnl_route_nh_get_ifindex(nh);
+ if (if_index > 0) {
+ p_val->set_if_index(if_index);
+
+ char if_name[IFNAMSIZ] = {0};
+ if_indextoname(if_index, if_name);
+ p_val->set_if_name(if_name);
+ }
+
+ // Source Address
+ addr = rtnl_route_get_pref_src(route);
+ if (addr) {
+ p_val->set_src_addr(*(in_addr_t *)nl_addr_get_binary_addr(addr));
+ }
+
+ // Table ID
+ int table_id = rtnl_route_get_table(route);
+ p_val->set_table_id(table_id);
+
+ // Metrics (e.g., MTU)
+ uint32_t mtu = 0;
+ int get_metric_result = rtnl_route_get_metric(route, RTAX_MTU, &mtu);
+ if (get_metric_result == 0) {
+ if (mtu > 0) {
+ p_val->set_mtu(mtu);
+ }
+ }
}
-bool route_table_mgr::find_route_val(in_addr_t &dst, uint32_t table_id, route_val* &p_val)
+bool route_table_mgr::find_route_val(in_addr_t &dst, uint32_t table_id, route_val *&p_val)
{
- ip_address dst_addr = dst;
- rt_mgr_logfunc("dst addr '%s'", dst_addr.to_str().c_str());
-
- route_val *correct_route_val = NULL;
- int longest_prefix = -1;
-
- for (int i = 0; i < m_tab.entries_num; i++) {
- route_val* p_val_from_tbl = &m_tab.value[i];
- if (!p_val_from_tbl->is_deleted() && p_val_from_tbl->is_if_up()) { // value was not deleted
- if(p_val_from_tbl->get_table_id() == table_id) { //found a match in routing table ID
- if(p_val_from_tbl->get_dst_addr() == (dst & p_val_from_tbl->get_dst_mask())) { //found a match in routing table
- if(p_val_from_tbl->get_dst_pref_len() > longest_prefix) { // this is the longest prefix match
- longest_prefix = p_val_from_tbl->get_dst_pref_len();
- correct_route_val = p_val_from_tbl;
- }
- }
- }
- }
- }
- if (correct_route_val) {
- ip_address dst_gw = correct_route_val->get_dst_addr();
- p_val = correct_route_val;
- rt_mgr_logdbg("found route val[%p]: %s", p_val, p_val->to_str());
- return true;
- }
-
- rt_mgr_logdbg("destination gw wasn't found");
- return false;
+ ip_address dst_addr = dst;
+ rt_mgr_logfunc("dst addr '%s'", dst_addr.to_str().c_str());
+
+ route_val *correct_route_val = NULL;
+ int longest_prefix = -1;
+
+ for (int i = 0; i < m_tab.entries_num; i++) {
+ route_val *p_val_from_tbl = &m_tab.value[i];
+ if (!p_val_from_tbl->is_deleted() && p_val_from_tbl->is_if_up()) { // value was not deleted
+ if (p_val_from_tbl->get_table_id() == table_id) { //found a match in routing table ID
+ if (p_val_from_tbl->get_dst_addr() ==
+ (dst & p_val_from_tbl->get_dst_mask())) { //found a match in routing table
+ if (p_val_from_tbl->get_dst_pref_len() >
+ longest_prefix) { // this is the longest prefix match
+ longest_prefix = p_val_from_tbl->get_dst_pref_len();
+ correct_route_val = p_val_from_tbl;
+ }
+ }
+ }
+ }
+ }
+ if (correct_route_val) {
+ ip_address dst_gw = correct_route_val->get_dst_addr();
+ p_val = correct_route_val;
+ rt_mgr_logdbg("found route val[%p]: %s", p_val, p_val->to_str());
+ return true;
+ }
+
+ rt_mgr_logdbg("destination gw wasn't found");
+ return false;
}
bool route_table_mgr::route_resolve(IN route_rule_table_key key, OUT route_result &res)
{
- in_addr_t dst = key.get_dst_ip();
- ip_address dst_addr = dst;
- rt_mgr_logdbg("dst addr '%s'", dst_addr.to_str().c_str());
-
- route_val *p_val = NULL;
- std::deque<uint32_t> table_id_list;
-
- g_p_rule_table_mgr->rule_resolve(key, table_id_list);
-
- auto_unlocker lock(m_lock);
- std::deque<uint32_t>::iterator table_id_iter = table_id_list.begin();
- for (; table_id_iter != table_id_list.end(); table_id_iter++) {
- if (find_route_val(dst, *table_id_iter, p_val)) {
- res.p_src = p_val->get_src_addr();
- rt_mgr_logdbg("dst ip '%s' resolved to src addr "
- "'%d.%d.%d.%d'", dst_addr.to_str().c_str(),
- NIPQUAD(res.p_src));
- res.p_gw = p_val->get_gw_addr();
- rt_mgr_logdbg("dst ip '%s' resolved to gw addr '%d.%d.%d.%d'",
- dst_addr.to_str().c_str(), NIPQUAD(res.p_gw));
- res.mtu = p_val->get_mtu();
- rt_mgr_logdbg("found route mtu %d", res.mtu);
- return true;
- }
- }
- /* prevent usage on false return */
- return false;
+ in_addr_t dst = key.get_dst_ip();
+ ip_address dst_addr = dst;
+ rt_mgr_logdbg("dst addr '%s'", dst_addr.to_str().c_str());
+
+ route_val *p_val = NULL;
+ std::deque<uint32_t> table_id_list;
+
+ g_p_rule_table_mgr->rule_resolve(key, table_id_list);
+
+ auto_unlocker lock(m_lock);
+ std::deque<uint32_t>::iterator table_id_iter = table_id_list.begin();
+ for (; table_id_iter != table_id_list.end(); table_id_iter++) {
+ if (find_route_val(dst, *table_id_iter, p_val)) {
+ res.p_src = p_val->get_src_addr();
+ rt_mgr_logdbg("dst ip '%s' resolved to src addr "
+ "'%d.%d.%d.%d'",
+ dst_addr.to_str().c_str(), NIPQUAD(res.p_src));
+ res.p_gw = p_val->get_gw_addr();
+ rt_mgr_logdbg("dst ip '%s' resolved to gw addr '%d.%d.%d.%d'",
+ dst_addr.to_str().c_str(), NIPQUAD(res.p_gw));
+ res.mtu = p_val->get_mtu();
+ rt_mgr_logdbg("found route mtu %d", res.mtu);
+ return true;
+ }
+ }
+ /* prevent usage on false return */
+ return false;
}
-void route_table_mgr::update_entry(INOUT route_entry* p_ent, bool b_register_to_net_dev /*= false*/)
+void route_table_mgr::update_entry(INOUT route_entry *p_ent, bool b_register_to_net_dev /*= false*/)
{
- rt_mgr_logdbg("entry [%p]", p_ent);
- auto_unlocker lock(m_lock);
- if (p_ent && !p_ent->is_valid()) { //if entry is found in the collection and is not valid
- rt_mgr_logdbg("route_entry is not valid-> update value");
- rule_entry* p_rr_entry = p_ent->get_rule_entry();
- std::deque<rule_val*>* p_rr_val;
- if (p_rr_entry && p_rr_entry->get_val(p_rr_val)) {
- route_val* p_val = NULL;
- in_addr_t peer_ip = p_ent->get_key().get_dst_ip();
- uint32_t table_id;
- for (std::deque<rule_val*>::iterator p_rule_val = p_rr_val->begin(); p_rule_val != p_rr_val->end(); p_rule_val++) {
- table_id = (*p_rule_val)->get_table_id();
- if (find_route_val(peer_ip, table_id, p_val)) {
- p_ent->set_val(p_val);
- if (b_register_to_net_dev) {
- //in_addr_t src_addr = p_val->get_src_addr();
- //net_device_val* p_ndv = g_p_net_device_table_mgr->get_net_device_val(src_addr);
-
- // Check if broadcast IP which is NOT supported
- if (IS_BROADCAST_N(peer_ip)) {
- rt_mgr_logdbg("Disabling Offload for route_entry '%s' - this is BC address", p_ent->to_str().c_str());
- // Need to route traffic to/from OS
- // Prevent registering of net_device to route entry
- }
- // Check if: Local loopback over Ethernet case which was not supported before OFED 2.1
- /*else if (p_ndv && (p_ndv->get_transport_type() == VMA_TRANSPORT_ETH) && (peer_ip == src_addr)) {
- rt_mgr_logdbg("Disabling Offload for route_entry '%s' - this is an Ethernet unicast loopback route", p_ent->to_str().c_str());
- // Need to route traffic to/from OS
- // Prevent registering of net_device to route entry
- }*/
- else {
- // register to net device for bonding events
- p_ent->register_to_net_device();
- }
- }
- // All good, validate the new route entry
- p_ent->set_entry_valid();
- break;
- } else {
- rt_mgr_logdbg("could not find route val for route_entry '%s in table %u'", p_ent->to_str().c_str(), table_id);
- }
- }
- }
- else {
- rt_mgr_logdbg("rule entry is not valid");
- }
- }
+ rt_mgr_logdbg("entry [%p]", p_ent);
+ auto_unlocker lock(m_lock);
+ if (p_ent && !p_ent->is_valid()) { //if entry is found in the collection and is not valid
+ rt_mgr_logdbg("route_entry is not valid-> update value");
+ rule_entry *p_rr_entry = p_ent->get_rule_entry();
+ std::deque<rule_val *> *p_rr_val;
+ if (p_rr_entry && p_rr_entry->get_val(p_rr_val)) {
+ route_val *p_val = NULL;
+ in_addr_t peer_ip = p_ent->get_key().get_dst_ip();
+ uint32_t table_id;
+ for (std::deque<rule_val *>::iterator p_rule_val = p_rr_val->begin();
+ p_rule_val != p_rr_val->end(); p_rule_val++) {
+ table_id = (*p_rule_val)->get_table_id();
+ if (find_route_val(peer_ip, table_id, p_val)) {
+ p_ent->set_val(p_val);
+ if (b_register_to_net_dev) {
+ //in_addr_t src_addr = p_val->get_src_addr();
+ //net_device_val* p_ndv =
+ //g_p_net_device_table_mgr->get_net_device_val(src_addr);
+
+ // Check if broadcast IP which is NOT supported
+ if (IS_BROADCAST_N(peer_ip)) {
+ rt_mgr_logdbg(
+ "Disabling Offload for route_entry '%s' - this is BC address",
+ p_ent->to_str().c_str());
+ // Need to route traffic to/from OS
+ // Prevent registering of net_device to route entry
+ }
+ // Check if: Local loopback over Ethernet case which was not supported
+ // before OFED 2.1
+ /*else if (p_ndv && (p_ndv->get_transport_type() == VMA_TRANSPORT_ETH) &&
+ (peer_ip == src_addr)) { rt_mgr_logdbg("Disabling Offload for route_entry
+ '%s' - this is an Ethernet unicast loopback route",
+ p_ent->to_str().c_str());
+ // Need to route traffic to/from OS
+ // Prevent registering of net_device to route entry
+ }*/
+ else {
+ // register to net device for bonding events
+ p_ent->register_to_net_device();
+ }
+ }
+ // All good, validate the new route entry
+ p_ent->set_entry_valid();
+ break;
+ } else {
+ rt_mgr_logdbg("could not find route val for route_entry '%s in table %u'",
+ p_ent->to_str().c_str(), table_id);
+ }
+ }
+ } else {
+ rt_mgr_logdbg("rule entry is not valid");
+ }
+ }
}
-route_entry* route_table_mgr::create_new_entry(route_rule_table_key key, const observer *obs)
+route_entry *route_table_mgr::create_new_entry(route_rule_table_key key, const observer *obs)
{
- // no need for lock - lock is activated in cache_collection_mgr::register_observer
-
- rt_mgr_logdbg("");
- NOT_IN_USE(obs);
- route_entry* p_ent = new route_entry(key);
- update_entry(p_ent, true);
- rt_mgr_logdbg("new entry %p created successfully", p_ent);
- return p_ent;
+ // no need for lock - lock is activated in cache_collection_mgr::register_observer
+
+ rt_mgr_logdbg("");
+ NOT_IN_USE(obs);
+ route_entry *p_ent = new route_entry(key);
+ update_entry(p_ent, true);
+ rt_mgr_logdbg("new entry %p created successfully", p_ent);
+ return p_ent;
}
-void route_table_mgr::new_route_event(route_val* netlink_route_val)
+void route_table_mgr::new_route_event(route_val *netlink_route_val)
{
- if (!netlink_route_val) {
- rt_mgr_logdbg("Invalid route entry");
- return;
- }
-
- if (m_tab.entries_num >= MAX_TABLE_SIZE) {
- rt_mgr_logwarn("No available space for new route entry");
- return;
- }
-
- auto_unlocker lock(m_lock);
- route_val* p_route_val = &m_tab.value[m_tab.entries_num];
- p_route_val->set_dst_addr(netlink_route_val->get_dst_addr());
- p_route_val->set_dst_mask(netlink_route_val->get_dst_mask());
- p_route_val->set_dst_pref_len(netlink_route_val->get_dst_pref_len());
- p_route_val->set_src_addr(netlink_route_val->get_src_addr());
- p_route_val->set_gw(netlink_route_val->get_gw_addr());
- p_route_val->set_protocol(netlink_route_val->get_protocol());
- p_route_val->set_scope(netlink_route_val->get_scope());
- p_route_val->set_type(netlink_route_val->get_type());
- p_route_val->set_table_id(netlink_route_val->get_table_id());
- p_route_val->set_if_index(netlink_route_val->get_if_index());
- p_route_val->set_if_name(const_cast<char*> (netlink_route_val->get_if_name()));
- p_route_val->set_mtu((netlink_route_val->get_mtu()));
- p_route_val->set_state(true);
- p_route_val->set_str();
- p_route_val->print_val();
- ++m_tab.entries_num;
+ if (!netlink_route_val) {
+ rt_mgr_logdbg("Invalid route entry");
+ return;
+ }
+
+ if (m_tab.entries_num >= MAX_TABLE_SIZE) {
+ rt_mgr_logwarn("No available space for new route entry");
+ return;
+ }
+
+ auto_unlocker lock(m_lock);
+ route_val *p_route_val = &m_tab.value[m_tab.entries_num];
+ p_route_val->set_dst_addr(netlink_route_val->get_dst_addr());
+ p_route_val->set_dst_mask(netlink_route_val->get_dst_mask());
+ p_route_val->set_dst_pref_len(netlink_route_val->get_dst_pref_len());
+ p_route_val->set_src_addr(netlink_route_val->get_src_addr());
+ p_route_val->set_gw(netlink_route_val->get_gw_addr());
+ p_route_val->set_protocol(netlink_route_val->get_protocol());
+ p_route_val->set_scope(netlink_route_val->get_scope());
+ p_route_val->set_type(netlink_route_val->get_type());
+ p_route_val->set_table_id(netlink_route_val->get_table_id());
+ p_route_val->set_if_index(netlink_route_val->get_if_index());
+ p_route_val->set_if_name(const_cast<char *>(netlink_route_val->get_if_name()));
+ p_route_val->set_mtu((netlink_route_val->get_mtu()));
+ p_route_val->set_state(true);
+ p_route_val->set_str();
+ p_route_val->print_val();
+ ++m_tab.entries_num;
}
void route_table_mgr::notify_cb(event *ev)
{
- rt_mgr_logdbg("received route event from netlink");
-
- route_nl_event *route_netlink_ev = dynamic_cast <route_nl_event*>(ev);
- if (!route_netlink_ev) {
- rt_mgr_logwarn("Received non route event!!!");
- return;
- }
-
- netlink_route_info* p_netlink_route_info = route_netlink_ev->get_route_info();
- if (!p_netlink_route_info) {
- rt_mgr_logdbg("Received invalid route event!!!");
- return;
- }
-
- switch(route_netlink_ev->nl_type) {
- case RTM_NEWROUTE:
- new_route_event(p_netlink_route_info->get_route_val());
- break;
+ rt_mgr_logdbg("received route event from netlink");
+
+ route_nl_event *route_netlink_ev = dynamic_cast<route_nl_event *>(ev);
+ if (!route_netlink_ev) {
+ rt_mgr_logwarn("Received non route event!!!");
+ return;
+ }
+
+ netlink_route_info *p_netlink_route_info = route_netlink_ev->get_route_info();
+ if (!p_netlink_route_info) {
+ rt_mgr_logdbg("Received invalid route event!!!");
+ return;
+ }
+
+ switch (route_netlink_ev->nl_type) {
+ case RTM_NEWROUTE:
+ new_route_event(p_netlink_route_info->get_route_val());
+ break;
#if 0
case RTM_DELROUTE:
del_route_event(p_netlink_route_info->get_route_val());
break;
#endif
- default:
- rt_mgr_logdbg("Route event (%u) is not handled", route_netlink_ev->nl_type);
- break;
- }
+ default:
+ rt_mgr_logdbg("Route event (%u) is not handled", route_netlink_ev->nl_type);
+ break;
+ }
}
diff --git a/src/vma/proto/route_table_mgr.h b/src/vma/proto/route_table_mgr.h
index fb0310f13..9a80945ae 100644
--- a/src/vma/proto/route_table_mgr.h
+++ b/src/vma/proto/route_table_mgr.h
@@ -30,7 +30,6 @@
* SOFTWARE.
*/
-
#ifndef ROUTE_TABLE_MGR_H
#define ROUTE_TABLE_MGR_H
@@ -45,47 +44,56 @@
#define ADDR_LEN 46 // needs 16-bytes for IPv4, and 46-bytes for IPv6
-typedef std::unordered_map<in_addr_t, route_entry*> in_addr_route_entry_map_t;
-typedef std::unordered_map<route_rule_table_key, cache_entry_subject<route_rule_table_key, route_val*> *> rt_tbl_cach_entry_map_t;
+typedef std::unordered_map<in_addr_t, route_entry *> in_addr_route_entry_map_t;
+typedef std::unordered_map<route_rule_table_key,
+ cache_entry_subject<route_rule_table_key, route_val *> *>
+ rt_tbl_cach_entry_map_t;
struct route_result {
- in_addr_t p_src;
- in_addr_t p_gw;
- uint32_t mtu;
- route_result(): p_src(0), p_gw(0) ,mtu(0) {}
+ in_addr_t p_src;
+ in_addr_t p_gw;
+ uint32_t mtu;
+ route_result()
+ : p_src(0)
+ , p_gw(0)
+ , mtu(0)
+ {
+ }
};
-class route_table_mgr : public netlink_socket_mgr<route_val>, public cache_table_mgr<route_rule_table_key, route_val*>, public observer
-{
+class route_table_mgr : public netlink_socket_mgr<route_val>,
+ public cache_table_mgr<route_rule_table_key, route_val *>,
+ public observer {
public:
- route_table_mgr();
- virtual ~route_table_mgr();
+ route_table_mgr();
+ virtual ~route_table_mgr();
- bool route_resolve(IN route_rule_table_key key, OUT route_result &res);
+ bool route_resolve(IN route_rule_table_key key, OUT route_result &res);
- route_entry* create_new_entry(route_rule_table_key key, const observer *obs);
- void update_entry(INOUT route_entry* p_ent, bool b_register_to_net_dev = false);
+ route_entry *create_new_entry(route_rule_table_key key, const observer *obs);
+ void update_entry(INOUT route_entry *p_ent, bool b_register_to_net_dev = false);
- virtual void notify_cb(event *ev);
+ virtual void notify_cb(event *ev);
protected:
- virtual bool parse_enrty(nlmsghdr *nl_header, route_val *p_val);
+ virtual bool parse_entry(struct nl_object *nl_obj, void *p_val_context);
private:
- // in constructor creates route_entry for each net_dev, to receive events in case there are no other route_entrys
- in_addr_route_entry_map_t m_rte_list_for_each_net_dev;
-
- bool find_route_val(in_addr_t &dst_addr, uint32_t table_id, route_val* &p_val);
-
- // save current main rt table
- void update_tbl();
- void parse_attr(struct rtattr *rt_attribute, route_val *p_val);
-
- void rt_mgr_update_source_ip();
-
- void new_route_event(route_val* netlink_route_val);
+ // in constructor creates route_entry for each net_dev, to receive events in case there are no
+ // other route_entrys
+ in_addr_route_entry_map_t m_rte_list_for_each_net_dev;
+
+ bool find_route_val(in_addr_t &dst_addr, uint32_t table_id, route_val *&p_val);
+
+ // save current main rt table
+ void update_tbl();
+ void parse_attr(struct rtnl_route *route, route_val *p_val);
+
+ void rt_mgr_update_source_ip();
+
+ void new_route_event(route_val *netlink_route_val);
};
-extern route_table_mgr* g_p_route_table_mgr;
+extern route_table_mgr *g_p_route_table_mgr;
#endif /* ROUTE_TABLE_MGR_H */
diff --git a/src/vma/proto/rule_table_mgr.cpp b/src/vma/proto/rule_table_mgr.cpp
index 32847014f..84ba80345 100644
--- a/src/vma/proto/rule_table_mgr.cpp
+++ b/src/vma/proto/rule_table_mgr.cpp
@@ -30,7 +30,6 @@
* SOFTWARE.
*/
-
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -53,228 +52,236 @@
#include "rule_table_mgr.h"
#include "vma/sock/socket_fd_api.h"
#include "vma/sock/sock-redirect.h"
-#include "ip_address.h"
// debugging macros
-#define MODULE_NAME "rrm:"
-
-#define rr_mgr_if_logpanic __log_panic
-#define rr_mgr_logerr __log_err
-#define rr_mgr_logwarn __log_warn
-#define rr_mgr_loginfo __log_info
-#define rr_mgr_logdbg __log_dbg
-#define rr_mgr_logfunc __log_func
-#define rr_mgr_logfuncall __log_funcall
-
-rule_table_mgr* g_p_rule_table_mgr = NULL;
-
-rule_table_mgr::rule_table_mgr() : netlink_socket_mgr<rule_val>(RULE_DATA_TYPE), cache_table_mgr<route_rule_table_key, std::deque<rule_val*>*>("rule_table_mgr")
+#define MODULE_NAME "rrm:"
+
+#define rr_mgr_if_logpanic __log_panic
+#define rr_mgr_logerr __log_err
+#define rr_mgr_logwarn __log_warn
+#define rr_mgr_loginfo __log_info
+#define rr_mgr_logdbg __log_dbg
+#define rr_mgr_logfunc __log_func
+#define rr_mgr_logfuncall __log_funcall
+
+rule_table_mgr *g_p_rule_table_mgr = NULL;
+
+rule_table_mgr::rule_table_mgr()
+ : netlink_socket_mgr<rule_val>(RULE_DATA_TYPE)
+ , cache_table_mgr<route_rule_table_key, std::deque<rule_val *> *>("rule_table_mgr")
{
- rr_mgr_logdbg("");
+ rr_mgr_logdbg("");
- //Read Rule table from kernel and save it in local variable.
- update_tbl();
-
- //Print table
- print_val_tbl();
-
- rr_mgr_logdbg("Done");
+ //Read Rule table from kernel and save it in local variable.
+ update_tbl();
+
+ //Print table
+ print_val_tbl();
+
+ rr_mgr_logdbg("Done");
}
//This function uses Netlink to get routing rules saved in kernel then saved it locally.
void rule_table_mgr::update_tbl()
{
- auto_unlocker lock(m_lock);
+ auto_unlocker lock(m_lock);
- netlink_socket_mgr<rule_val>::update_tbl();
+ netlink_socket_mgr<rule_val>::update_tbl();
- return;
+ return;
}
// Parse received rule entry into custom object (rule_val).
-// Parameters:
+// Parameters:
// nl_header : object that contain rule entry.
// p_val : custom object that contain parsed rule data.
// return true if its not related to local or default table, false otherwise.
-bool rule_table_mgr::parse_enrty(nlmsghdr *nl_header, rule_val *p_val)
+bool rule_table_mgr::parse_entry(struct nl_object *nl_obj, void *p_val_context)
{
- int len;
- struct rtmsg *rt_msg;
- struct rtattr *rt_attribute;
-
- // get rule entry header
- rt_msg = (struct rtmsg *) NLMSG_DATA(nl_header);
-
- // we are not concerned about the local and default rule table
- if (rt_msg->rtm_family != AF_INET || rt_msg->rtm_table == RT_TABLE_LOCAL)
- return false;
-
- p_val->set_protocol(rt_msg->rtm_protocol);
- p_val->set_scope(rt_msg->rtm_scope);
- p_val->set_type(rt_msg->rtm_type);
- p_val->set_tos(rt_msg->rtm_tos);
- p_val->set_table_id(rt_msg->rtm_table);
-
- len = RTM_PAYLOAD(nl_header);
- rt_attribute = (struct rtattr *) RTM_RTA(rt_msg);
-
- for (;RTA_OK(rt_attribute, len);rt_attribute=RTA_NEXT(rt_attribute,len)) {
- parse_attr(rt_attribute, p_val);
- }
- p_val->set_state(true);
- p_val->set_str();
- return true;
+ rule_val *p_val = static_cast<rule_val *>(p_val_context);
+ // Cast the generic nl_object to a specific route or rule object
+ struct rtnl_rule *rule = reinterpret_cast<struct rtnl_rule *>(nl_obj);
+
+ uint32_t table_id = rtnl_rule_get_table(rule);
+ if (rtnl_rule_get_family(rule) != AF_INET || table_id == RT_TABLE_LOCAL) {
+ return false;
+ }
+
+ p_val->set_tos(rtnl_rule_get_dsfield(rule));
+ p_val->set_table_id(table_id);
+
+ parse_attr(rule, p_val);
+
+ p_val->set_state(true);
+ p_val->set_str();
+ return true;
}
// Parse received rule attribute for given rule.
-// Parameters:
+// Parameters:
// rt_attribute : object that contain rule attribute.
// p_val : custom object that contain parsed rule data.
-void rule_table_mgr::parse_attr(struct rtattr *rt_attribute, rule_val *p_val)
+void rule_table_mgr::parse_attr(struct rtnl_rule *rule, rule_val *p_val)
{
- switch (rt_attribute->rta_type) {
- case FRA_PRIORITY:
- p_val->set_priority(*(uint32_t *)RTA_DATA(rt_attribute));
- break;
- case FRA_DST:
- p_val->set_dst_addr(*(in_addr_t *)RTA_DATA(rt_attribute));
- break;
- case FRA_SRC:
- p_val->set_src_addr(*(in_addr_t *)RTA_DATA(rt_attribute));
- break;
- case FRA_IFNAME:
- p_val->set_iif_name((char *)RTA_DATA(rt_attribute));
- break;
- case FRA_TABLE:
- p_val->set_table_id(*(uint32_t *)RTA_DATA(rt_attribute));
- break;
+ // FRA_PRIORITY: Rule Priority
+ uint32_t priority = rtnl_rule_get_prio(rule);
+ if (priority) {
+ p_val->set_priority(priority);
+ }
+
+ // FRA_DST: Destination Address
+ struct nl_addr *dst = rtnl_rule_get_dst(rule);
+ if (dst) {
+ p_val->set_dst_addr(*(in_addr_t *)nl_addr_get_binary_addr(dst));
+ }
+
+ // FRA_SRC: Source Address
+ struct nl_addr *src = rtnl_rule_get_src(rule);
+ if (src) {
+ p_val->set_src_addr(*(in_addr_t *)nl_addr_get_binary_addr(src));
+ }
+
+ // FRA_IFNAME: Input Interface Name
+ char *iif_name = rtnl_rule_get_iif(rule);
+ if (iif_name) {
+ p_val->set_iif_name(iif_name);
+ }
+
+ // FRA_TABLE: Table ID
+ uint32_t table_id = rtnl_rule_get_table(rule);
+ if (table_id) {
+ p_val->set_table_id(table_id);
+ }
+
#if DEFINED_FRA_OIFNAME
- case FRA_OIFNAME:
- p_val->set_oif_name((char *)RTA_DATA(rt_attribute));
- break;
+ // FRA_OIFNAME: Output Interface Name (if available)
+ char *oif_name = rtnl_rule_get_oif(rule);
+ if (oif_name) {
+ p_val->set_oif_name(oif_name);
+ }
#endif
- default:
- rr_mgr_logdbg("got undetected rta_type %d %x", rt_attribute->rta_type, *(uint32_t *)RTA_DATA(rt_attribute));
- break;
- }
}
-
-// Create rule entry object for given destination key and fill it with matching rule value from rule table.
-// Parameters:
+// Create rule entry object for given destination key and fill it with matching rule value from rule
+// table. Parameters:
// key : key object that contain information about destination.
// obs : object that contain observer for specific rule entry.
// Returns created rule entry object.
-rule_entry* rule_table_mgr::create_new_entry(route_rule_table_key key, const observer *obs)
+rule_entry *rule_table_mgr::create_new_entry(route_rule_table_key key, const observer *obs)
{
- rr_mgr_logdbg("");
- NOT_IN_USE(obs);
- rule_entry* p_ent = new rule_entry(key);
- update_entry(p_ent);
- rr_mgr_logdbg("new entry %p created successfully", p_ent);
- return p_ent;
+ rr_mgr_logdbg("");
+ NOT_IN_USE(obs);
+ rule_entry *p_ent = new rule_entry(key);
+ update_entry(p_ent);
+ rr_mgr_logdbg("new entry %p created successfully", p_ent);
+ return p_ent;
}
// Update invalid rule entry with matching rule value from rule table.
-// Parameters:
+// Parameters:
// p_ent : rule entry that will be updated if it is invalid.
-void rule_table_mgr::update_entry(rule_entry* p_ent)
+void rule_table_mgr::update_entry(rule_entry *p_ent)
{
- rr_mgr_logdbg("entry [%p]", p_ent);
- auto_unlocker lock(m_lock);
-
- if (p_ent && !p_ent->is_valid()) { //if entry is found in the collection and is not valid
-
- rr_mgr_logdbg("rule_entry is not valid-> update value");
- std::deque<rule_val*>* p_rrv;
- p_ent->get_val(p_rrv);
- /* p_rrv->clear(); TODO for future rule live updates */
- if (!find_rule_val(p_ent->get_key(), p_rrv)) {
- rr_mgr_logdbg("ERROR: could not find rule val for rule_entry '%s'", p_ent->to_str().c_str());
- }
- }
+ rr_mgr_logdbg("entry [%p]", p_ent);
+ auto_unlocker lock(m_lock);
+
+ if (p_ent && !p_ent->is_valid()) { //if entry is found in the collection and is not valid
+
+ rr_mgr_logdbg("rule_entry is not valid-> update value");
+ std::deque<rule_val *> *p_rrv;
+ p_ent->get_val(p_rrv);
+ /* p_rrv->clear(); TODO for future rule live updates */
+ if (!find_rule_val(p_ent->get_key(), p_rrv)) {
+ rr_mgr_logdbg("ERROR: could not find rule val for rule_entry '%s'",
+ p_ent->to_str().c_str());
+ }
+ }
}
-// Find rule form rule table that match given destination info.
-// Parameters:
+// Find rule form rule table that match given destination info.
+// Parameters:
// key : key object that contain information about destination.
-// p_val : list of rule_val object that will contain information about all rule that match destination info
+// p_val : list of rule_val object that will contain information about all rule that match
+//destination info
// Returns true if at least one rule match destination info, false otherwise.
-bool rule_table_mgr::find_rule_val(route_rule_table_key key, std::deque<rule_val*>* &p_val)
+bool rule_table_mgr::find_rule_val(route_rule_table_key key, std::deque<rule_val *> *&p_val)
{
- rr_mgr_logfunc("destination info %s:", key.to_str().c_str());
+ rr_mgr_logfunc("destination info %s:", key.to_str().c_str());
- for (int index = 0; index < m_tab.entries_num; index++) {
- rule_val* p_val_from_tbl = &m_tab.value[index];
- if (p_val_from_tbl->is_valid() && is_matching_rule(key, p_val_from_tbl)) {
- p_val->push_back(p_val_from_tbl);
- rr_mgr_logdbg("found rule val[%p]: %s", p_val_from_tbl, p_val_from_tbl->to_str());
- }
- }
+ for (int index = 0; index < m_tab.entries_num; index++) {
+ rule_val *p_val_from_tbl = &m_tab.value[index];
+ if (p_val_from_tbl->is_valid() && is_matching_rule(key, p_val_from_tbl)) {
+ p_val->push_back(p_val_from_tbl);
+ rr_mgr_logdbg("found rule val[%p]: %s", p_val_from_tbl, p_val_from_tbl->to_str());
+ }
+ }
- return !p_val->empty();
+ return !p_val->empty();
}
-// Check matching between given destination info. and specific rule from rule table.
-// Parameters:
+// Check matching between given destination info. and specific rule from rule table.
+// Parameters:
// key : key object that contain information about destination.
-// p_val : rule_val object that contain information about specific rule from rule table
+// p_val : rule_val object that contain information about specific rule from rule table
// Returns true if destination info match rule value, false otherwise.
-bool rule_table_mgr::is_matching_rule(route_rule_table_key key, rule_val* p_val)
+bool rule_table_mgr::is_matching_rule(route_rule_table_key key, rule_val *p_val)
{
- in_addr_t m_dst_ip = key.get_dst_ip();
- in_addr_t m_src_ip = key.get_src_ip();
- uint8_t m_tos = key.get_tos();
-
- in_addr_t rule_dst_ip = p_val->get_dst_addr();
- in_addr_t rule_src_ip = p_val->get_src_addr();
- uint8_t rule_tos = p_val->get_tos();
- char* rule_iif_name = (char *)p_val->get_iif_name();
- char* rule_oif_name = (char *)p_val->get_oif_name();
-
- bool is_match = false;
-
- // Only destination IP, source IP and TOS are checked with rule, since IIF and OIF is not filled in dst_entry object.
- if ((rule_dst_ip == 0) || (rule_dst_ip == m_dst_ip)) { // Check match in destination IP
-
- if ((rule_src_ip == 0) || (rule_src_ip == m_src_ip)) { // Check match in source IP
-
- if ((rule_tos == 0) || (rule_tos == m_tos)) { // Check match in TOS value
-
- if (strcmp(rule_iif_name, "") == 0) { // Check that rule doesn't contain IIF since we can't check match with
-
- if (strcmp(rule_oif_name, "") == 0) { // Check that rule doesn't contain OIF since we can't check match with
- is_match = true;
- }
- }
- }
- }
- }
-
- return is_match;
+ in_addr_t m_dst_ip = key.get_dst_ip();
+ in_addr_t m_src_ip = key.get_src_ip();
+ uint8_t m_tos = key.get_tos();
+
+ in_addr_t rule_dst_ip = p_val->get_dst_addr();
+ in_addr_t rule_src_ip = p_val->get_src_addr();
+ uint8_t rule_tos = p_val->get_tos();
+ char *rule_iif_name = (char *)p_val->get_iif_name();
+ char *rule_oif_name = (char *)p_val->get_oif_name();
+
+ bool is_match = false;
+
+ // Only destination IP, source IP and TOS are checked with rule, since IIF and OIF is not filled
+ // in dst_entry object.
+ if ((rule_dst_ip == 0) || (rule_dst_ip == m_dst_ip)) { // Check match in destination IP
+
+ if ((rule_src_ip == 0) || (rule_src_ip == m_src_ip)) { // Check match in source IP
+
+ if ((rule_tos == 0) || (rule_tos == m_tos)) { // Check match in TOS value
+
+ if (strcmp(rule_iif_name, "") ==
+ 0) { // Check that rule doesn't contain IIF since we can't check match with
+
+ if (strcmp(rule_oif_name, "") ==
+ 0) { // Check that rule doesn't contain OIF since we can't check match with
+ is_match = true;
+ }
+ }
+ }
+ }
+ }
+
+ return is_match;
}
// Find table ID for given destination info.
-// Parameters:
+// Parameters:
// key : key object that contain information about destination.
-// table_id_list : list that will contain table ID for all rule that match destination info
+// table_id_list : list that will contain table ID for all rule that match destination info
// Returns true if at least one rule match destination info, false otherwise.
bool rule_table_mgr::rule_resolve(route_rule_table_key key, std::deque<uint32_t> &table_id_list)
{
- rr_mgr_logdbg("dst info: '%s'", key.to_str().c_str());
-
- std::deque<rule_val*> values;
- std::deque<rule_val*>* p_values = &values;
- auto_unlocker lock(m_lock);
- if (find_rule_val(key, p_values)) {
- for (std::deque<rule_val*>::iterator val = values.begin(); val != values.end(); val++) {
- table_id_list.push_back((*val)->get_table_id());
- rr_mgr_logdbg("dst info: '%s' resolved to table ID '%u'", key.to_str().c_str(), (*val)->get_table_id());
- }
- }
-
- return !table_id_list.empty();
-}
+ rr_mgr_logdbg("dst info: '%s'", key.to_str().c_str());
+
+ std::deque<rule_val *> values;
+ std::deque<rule_val *> *p_values = &values;
+ auto_unlocker lock(m_lock);
+ if (find_rule_val(key, p_values)) {
+ for (std::deque<rule_val *>::iterator val = values.begin(); val != values.end(); val++) {
+ table_id_list.push_back((*val)->get_table_id());
+ rr_mgr_logdbg("dst info: '%s' resolved to table ID '%u'", key.to_str().c_str(),
+ (*val)->get_table_id());
+ }
+ }
+ return !table_id_list.empty();
+}
diff --git a/src/vma/proto/rule_table_mgr.h b/src/vma/proto/rule_table_mgr.h
index f3f6fdcf7..4d2c68361 100644
--- a/src/vma/proto/rule_table_mgr.h
+++ b/src/vma/proto/rule_table_mgr.h
@@ -30,7 +30,6 @@
* SOFTWARE.
*/
-
#ifndef RULE_TABLE_MGR_H
#define RULE_TABLE_MGR_H
@@ -41,30 +40,29 @@
#include "rule_entry.h"
/*
-* This class manages routing rule related operation such as getting rules from kernel,
-* finding table ID for given destination info and cashing usage history for rule table.
-*/
-class rule_table_mgr : public netlink_socket_mgr<rule_val>, public cache_table_mgr<route_rule_table_key, std::deque<rule_val*>*>
-{
+ * This class manages routing rule related operation such as getting rules from kernel,
+ * finding table ID for given destination info and cashing usage history for rule table.
+ */
+class rule_table_mgr : public netlink_socket_mgr<rule_val>,
+ public cache_table_mgr<route_rule_table_key, std::deque<rule_val *> *> {
public:
- rule_table_mgr();
-
- rule_entry* create_new_entry(route_rule_table_key key, const observer *obs);
- void update_entry(rule_entry* p_ent);
- bool rule_resolve(route_rule_table_key key, std::deque<uint32_t> &table_id_list);
+ rule_table_mgr();
+
+ rule_entry *create_new_entry(route_rule_table_key key, const observer *obs);
+ void update_entry(rule_entry *p_ent);
+ bool rule_resolve(route_rule_table_key key, std::deque<uint32_t> &table_id_list);
protected:
- virtual bool parse_enrty(nlmsghdr *nl_header, rule_val *p_val);
- virtual void update_tbl();
-
+ virtual bool parse_entry(struct nl_object *nl_obj, void *p_val_context);
+ virtual void update_tbl();
+
private:
+ void parse_attr(struct rtnl_rule *rule, rule_val *p_val);
- void parse_attr(struct rtattr *rt_attribute, rule_val *p_val);
-
- bool find_rule_val(route_rule_table_key key, std::deque<rule_val*>* &p_val);
- bool is_matching_rule(route_rule_table_key rrk, rule_val* p_val);
+ bool find_rule_val(route_rule_table_key key, std::deque<rule_val *> *&p_val);
+ bool is_matching_rule(route_rule_table_key rrk, rule_val *p_val);
};
-extern rule_table_mgr* g_p_rule_table_mgr;
+extern rule_table_mgr *g_p_rule_table_mgr;
#endif /* RULE_TABLE_MGR_H */
diff --git a/src/vma/proto/rule_val.cpp b/src/vma/proto/rule_val.cpp
index 3c56f4561..937a419eb 100644
--- a/src/vma/proto/rule_val.cpp
+++ b/src/vma/proto/rule_val.cpp
@@ -30,7 +30,6 @@
* SOFTWARE.
*/
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -38,76 +37,77 @@
#include "rule_val.h"
#include "rule_table_mgr.h"
-#define MODULE_NAME "rrv"
+#define MODULE_NAME "rrv"
-#define rr_val_loginfo __log_info_info
-#define rr_val_logdbg __log_info_dbg
-#define rr_val_logfunc __log_info_func
+#define rr_val_loginfo __log_info_info
+#define rr_val_logdbg __log_info_dbg
+#define rr_val_logfunc __log_info_func
-rule_val::rule_val(): cache_observer()
+rule_val::rule_val()
+ : cache_observer()
{
- m_protocol = 0;
- m_scope = 0;
- m_type = 0;
- m_dst_addr = 0;
- m_src_addr = 0;
- memset(m_oif_name, 0, IFNAMSIZ * sizeof(char));
- memset(m_iif_name, 0, IFNAMSIZ * sizeof(char));
- m_priority = 0;
- m_tos = 0;
- m_table_id = 0;
- m_is_valid = false;
- memset(m_str, 0, BUFF_SIZE * sizeof(char));
-
+ m_dst_addr = 0;
+ m_src_addr = 0;
+ memset(m_oif_name, 0, IFNAMSIZ * sizeof(char));
+ memset(m_iif_name, 0, IFNAMSIZ * sizeof(char));
+ m_priority = 0;
+ m_tos = 0;
+ m_table_id = 0;
+ m_is_valid = false;
+ memset(m_str, 0, BUFF_SIZE * sizeof(char));
}
//This function build string that represent a row in the rule table.
void rule_val::set_str()
{
- char str_addr[INET_ADDRSTRLEN];
- char str_x[100] = {0};
+ char str_addr[INET_ADDRSTRLEN];
+ char str_x[100] = {0};
- sprintf(m_str, "Priority :%-10u", m_priority);
+ sprintf(m_str, "Priority :%-10u", m_priority);
- if (m_src_addr != 0) {
- inet_ntop(AF_INET, &m_src_addr_in_addr, str_addr, sizeof(str_addr));
- sprintf(str_x, " from :%-10s", str_addr);
- }
- strcat(m_str, str_x);
+ if (m_src_addr != 0) {
+ inet_ntop(AF_INET, &m_src_addr_in_addr, str_addr, sizeof(str_addr));
+ sprintf(str_x, " from :%-10s", str_addr);
+ }
+ strcat(m_str, str_x);
- str_x[0] = '\0';
- if (m_dst_addr != 0) {
- inet_ntop(AF_INET, &m_dst_addr_in_addr, str_addr, sizeof(str_addr));
- sprintf(str_x, " to :%-12s", str_addr);
- }
- strcat(m_str, str_x);
+ str_x[0] = '\0';
+ if (m_dst_addr != 0) {
+ inet_ntop(AF_INET, &m_dst_addr_in_addr, str_addr, sizeof(str_addr));
+ sprintf(str_x, " to :%-12s", str_addr);
+ }
+ strcat(m_str, str_x);
- str_x[0] = '\0';
- if (m_tos != 0)
- sprintf(str_x, " tos :%-11u", m_tos);
- strcat(m_str, str_x);
+ str_x[0] = '\0';
+ if (m_tos != 0) {
+ sprintf(str_x, " tos :%-11u", m_tos);
+ }
+ strcat(m_str, str_x);
- str_x[0] = '\0';
- if (strcmp(m_iif_name, "") != 0)
- sprintf(str_x, " iif :%-11s", m_iif_name);
- strcat(m_str, str_x);
+ str_x[0] = '\0';
+ if (strcmp(m_iif_name, "") != 0) {
+ sprintf(str_x, " iif :%-11s", m_iif_name);
+ }
+ strcat(m_str, str_x);
- str_x[0] = '\0';
- if (strcmp(m_oif_name, "") != 0)
- sprintf(str_x, " oif :%-11s", m_oif_name);
- strcat(m_str, str_x);
+ str_x[0] = '\0';
+ if (strcmp(m_oif_name, "") != 0) {
+ sprintf(str_x, " oif :%-11s", m_oif_name);
+ }
+ strcat(m_str, str_x);
- str_x[0] = '\0';
- if (m_table_id != RT_TABLE_MAIN)
- sprintf(str_x, " lookup table :%-10u", m_table_id);
- else
- sprintf(str_x, " lookup table :%-10s", "main");
- strcat(m_str, str_x);
+ str_x[0] = '\0';
+ if (m_table_id != RT_TABLE_MAIN) {
+ sprintf(str_x, " lookup table :%-10u", m_table_id);
+ } else {
+ sprintf(str_x, " lookup table :%-10s", "main");
+ }
+ strcat(m_str, str_x);
}
//This function prints a string that represent a row in the rule table as debug log.
void rule_val::print_val()
{
- set_str();
- rr_val_logdbg("%s", to_str());
+ set_str();
+ rr_val_logdbg("%s", to_str());
}
diff --git a/src/vma/proto/rule_val.h b/src/vma/proto/rule_val.h
index 9d6f8d200..80ec81f7c 100644
--- a/src/vma/proto/rule_val.h
+++ b/src/vma/proto/rule_val.h
@@ -30,7 +30,6 @@
* SOFTWARE.
*/
-
#ifndef RULE_VAL_H
#define RULE_VAL_H
@@ -44,61 +43,53 @@
/*
This class will contain information for given routing rule entry.
*/
-class rule_val : public cache_observer
-{
+class rule_val : public cache_observer {
public:
- rule_val();
- virtual ~rule_val() {};
+ rule_val();
+ virtual ~rule_val() {};
- inline void set_dst_addr(in_addr_t const &dst_addr) { m_dst_addr = dst_addr; };
- inline void set_src_addr(in_addr_t const &src_addr) { m_src_addr = src_addr; };
- inline void set_protocol(unsigned char protocol) { m_protocol = protocol; };
- inline void set_scope(unsigned char scope) { m_scope = scope; };
- inline void set_type(unsigned char type) { m_type = type; };
- inline void set_tos(unsigned char tos) { m_tos = tos; };
- inline void set_table_id(uint32_t table_id) { m_table_id = table_id; };
- inline void set_iif_name(char *iif_name) { memcpy(m_iif_name, iif_name, IFNAMSIZ); };
- inline void set_oif_name(char *oif_name) { memcpy(m_oif_name, oif_name, IFNAMSIZ); };
- inline void set_priority(uint32_t priority) { m_priority = priority; };
+ inline void set_dst_addr(in_addr_t const &dst_addr) { m_dst_addr = dst_addr; };
+ inline void set_src_addr(in_addr_t const &src_addr) { m_src_addr = src_addr; };
+ inline void set_tos(unsigned char tos) { m_tos = tos; };
+ inline void set_table_id(uint32_t table_id) { m_table_id = table_id; };
+ inline void set_iif_name(char *iif_name) { memcpy(m_iif_name, iif_name, IFNAMSIZ); };
+ inline void set_oif_name(char *oif_name) { memcpy(m_oif_name, oif_name, IFNAMSIZ); };
+ inline void set_priority(uint32_t priority) { m_priority = priority; };
- void set_str();
+ void set_str();
- inline in_addr_t get_dst_addr() const { return m_dst_addr; };
- inline in_addr_t get_src_addr() const { return m_src_addr; };
- inline unsigned char get_tos() const { return m_tos; };
- inline uint32_t get_table_id() const { return m_table_id; };
- inline const char* get_iif_name() const { return m_iif_name; };
- inline const char* get_oif_name() const { return m_oif_name; };
+ inline in_addr_t get_dst_addr() const { return m_dst_addr; };
+ inline in_addr_t get_src_addr() const { return m_src_addr; };
+ inline unsigned char get_tos() const { return m_tos; };
+ inline uint32_t get_table_id() const { return m_table_id; };
+ inline const char *get_iif_name() const { return m_iif_name; };
+ inline const char *get_oif_name() const { return m_oif_name; };
- inline void set_state(bool state) { m_is_valid = state; };
- inline bool is_valid() const { return m_is_valid; };
+ inline void set_state(bool state) { m_is_valid = state; };
+ inline bool is_valid() const { return m_is_valid; };
- void print_val();
- char* to_str() { return m_str; };
+ void print_val();
+ char *to_str() { return m_str; };
private:
+ unsigned char m_tos;
+
+ union {
+ in_addr_t m_dst_addr;
+ in_addr m_dst_addr_in_addr;
+ };
+ union {
+ in_addr_t m_src_addr;
+ in_addr m_src_addr_in_addr;
+ };
+ char m_iif_name[IFNAMSIZ];
+ char m_oif_name[IFNAMSIZ];
+ uint32_t m_priority;
+ uint32_t m_table_id;
- unsigned char m_protocol;
- unsigned char m_scope;
- unsigned char m_type;
- unsigned char m_tos;
+ bool m_is_valid;
- union {
- in_addr_t m_dst_addr;
- in_addr m_dst_addr_in_addr;
- };
- union {
- in_addr_t m_src_addr;
- in_addr m_src_addr_in_addr;
- };
- char m_iif_name[IFNAMSIZ];
- char m_oif_name[IFNAMSIZ];
- uint32_t m_priority;
- uint32_t m_table_id;
-
- bool m_is_valid;
-
- char m_str[BUFF_SIZE];
+ char m_str[BUFF_SIZE];
};
#endif /* RULE_VAL_H */