2132 lines
72 KiB
Diff
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 */
|