OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ksync_memory.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <sys/socket.h>
6 #if defined(__linux__)
7 #include <linux/netlink.h>
8 #endif
9 #include <fcntl.h>
10 #include <sys/mman.h>
11 #include <sys/types.h>
12 #include <sys/ipc.h>
13 #include <sys/shm.h>
14 #include <asm/types.h>
15 #include <boost/asio.hpp>
16 
17 #include <base/timer.h>
18 #include <base/task_trigger.h>
19 #include <base/address_util.h>
20 #include <cmn/agent_cmn.h>
21 #include <services/services_init.h>
22 #include <uve/stats_collector.h>
24 #include <pkt/flow_proto.h>
25 #include <ksync/ksync_index.h>
26 #include <ksync/ksync_entry.h>
27 #include <ksync/ksync_object.h>
28 #include <ksync/ksync_netlink.h>
29 #include <ksync/ksync_sock.h>
30 #include <ksync/ksync_sock_user.h>
31 
32 #include <vr_types.h>
33 #include <nl_util.h>
34 #include <vr_flow.h>
35 #include <ini_parser.h>
36 #include <vr_genetlink.h>
37 
38 #include "ksync_init.h"
39 #include "ksync_flow_memory.h"
40 #include "sandesh_ksync.h"
41 #include "init/agent_param.h"
42 
43 using namespace boost::asio::ip;
44 static const int kTestFlowTableSize = 131072 * sizeof(vr_flow_entry);
45 
46 KSyncMemory::KSyncMemory(KSync *ksync, uint32_t minor_id) :
47  ksync_(ksync),
48  table_path_(),
49  major_devid_(0),
50  minor_devid_(minor_id),
51  table_size_(0),
52  table_entries_count_(0),
53  audit_timer_(TimerManager::CreateTimer
54  (*(ksync->agent()->event_manager())->io_service(),
55  " Audit Timer",
56  ksync->agent()->task_scheduler()->GetTaskId(kTaskFlowAudit),
57  0)),
58  audit_timeout_(0),
59  audit_yield_(0),
60  audit_interval_(0),
61  audit_idx_(0),
62  audit_list_() {
63 }
64 
67 }
68 
72  uint32_t table_count = table_entries_count_;
73  // Compute number of entries to visit per timer interval so that complete
74  // table can be visited in kAuditSweepTime
75  uint32_t timer_per_sec = 1000 / kAuditYieldTimer;
76  uint32_t timer_per_sweep = kAuditSweepTime * timer_per_sec;
77  audit_yield_ = table_count / timer_per_sweep;
82 
84  boost::bind(&KSyncMemory::AuditProcess, this));
85 }
86 
87 void KSyncMemory::Mmap(bool unlink_node, void *khpmem, bool kernel_mode) {
88  // In case of non hugepage kernel mode,
89  // Remove the existing /dev/ file first. We will add it again in vr_table_map
90  if (!khpmem && unlink_node) {
91  const char *error_msg = vr_table_unlink(table_path_.c_str());
92  if (error_msg) {
93  LOG(ERROR, "Error unmapping KSync memory: " << error_msg);
94  assert(0);
95  }
96  }
97  parse_ini_file();
98 
99  // Kernel hugepage present
100  if (khpmem) {
101  table_ = khpmem;
102  } else {
103  // DPDK or kernel without hugepage support
104  const char *table_str;
105  if (kernel_mode) {
106  table_str = NULL;
107  } else {
108  table_str = table_path_.c_str();
109  }
110  const char *mmap_error_msg = vr_table_map(major_devid_, minor_devid_, table_str,
111  table_size_, &table_);
112  if (mmap_error_msg) {
113  LOG(ERROR, "Error mapping KSync memory. Device: " << table_path_ << "; " << mmap_error_msg);
114  assert(0);
115  }
116  LOG(INFO, "Mem mapped dev file:" << table_path_.c_str() << " to addr:" << table_ << "\n");
117  }
118 
120  SetTableSize();
121 }
122 
124  struct nl_client *cl;
125  int attr_len;
126  int encode_len, ret;
127 
128  assert((cl = nl_register_client()) != NULL);
129 
130  assert(nl_socket(cl, AF_NETLINK, SOCK_DGRAM, NETLINK_GENERIC) > 0);
131  assert(nl_connect(cl, 0, 0, 0) == 0);
132 
133  assert(vrouter_obtain_family_id(cl) > 0);
134 
135  assert(nl_build_nlh(cl, cl->cl_genl_family_id, NLM_F_REQUEST) == 0);
136  assert(nl_build_genlh(cl, SANDESH_REQUEST, 0) == 0);
137 
138  attr_len = nl_get_attr_hdr_size();
139 
140  encode_len = EncodeReq(cl, attr_len);
141  nl_build_attr(cl, encode_len, NL_ATTR_VR_MESSAGE_PROTOCOL);
142  nl_update_nlh(cl);
143 
144  if ((ret = nl_sendmsg(cl)) < 0) {
145  LOG(DEBUG, "Error requesting Table message. Error : " << ret);
146  assert(0);
147  }
148 
149  while ((ret = nl_recvmsg(cl)) > 0) {
152  }
153  nl_free_client(cl);
154  return table_size_;
155 }
156 
157 // Steps to map table entry
158 // In case of non huge pages
159 // - Query the table parameters from kernel
160 // - Create device /dev/ with major-num and minor-num
161 // - Map device memory
162 // In case of huge pages
163 // - Just use the huge page memory which is initialized
164 // and passed to this function
165 void KSyncMemory::InitMem(void *hpmem) {
167  Mmap(true, hpmem, true);
168  return;
169 }
170 
172  assert(0);
173 }
174 
176  assert(0);
177 }
178 
180  // Get current time
181  uint64_t t = UTCTimestampUsec();
182 
183  while (!audit_list_.empty()) {
184  AuditEntry list_entry = audit_list_.front();
185  // audit_list_ is sorted on last time of insertion in the list
186  // So, break on finding first entry that cannot be aged
187  if ((t - list_entry.timeout) < audit_timeout_) {
188  /* Wait for audit_timeout_ to create short for the entry */
189  break;
190  }
191  uint32_t idx = list_entry.audit_idx;
192  uint32_t gen_id = list_entry.audit_gen_id;
193  audit_list_.pop_front();
195  CreateProtoAuditEntry(idx, gen_id);
196  }
197 
198  uint32_t count = 0;
199  uint8_t gen_id;
200  assert(audit_yield_);
201  while (count < audit_yield_) {
202  if (IsInactiveEntry(audit_idx_, gen_id)) {
204  audit_list_.push_back(AuditEntry(audit_idx_, gen_id, t));
205  }
206 
207  count++;
208  audit_idx_++;
211  audit_idx_ = 0;
212  }
213  }
214  return true;
215 }
216 
218  struct nl_client *cl;
219  int attr_len;
220  int encode_len;
221 
222  assert((cl = nl_register_client()) != NULL);
223  cl->cl_genl_family_id = KSyncSock::GetNetlinkFamilyId();
224  assert(nl_build_nlh(cl, cl->cl_genl_family_id, NLM_F_REQUEST) == 0);
225  assert(nl_build_genlh(cl, SANDESH_REQUEST, 0) == 0);
226 
227  attr_len = nl_get_attr_hdr_size();
228  encode_len = EncodeReq(cl, attr_len);
229  nl_build_attr(cl, encode_len, NL_ATTR_VR_MESSAGE_PROTOCOL);
230  nl_update_nlh(cl);
231  string ksync_agent_vrouter_sock_path = KSYNC_AGENT_VROUTER_SOCK_PATH;
232  ksync_agent_vrouter_sock_path =
234  ksync_->agent()->params()->cat_ksocketdir() +
235  "dpdk_netlink" : ksync_agent_vrouter_sock_path;
236 
237 #ifdef AGENT_VROUTER_TCP
238  tcp::socket socket(*(ksync_->agent()->event_manager()->io_service()));
239  tcp::endpoint endpoint(ksync_->agent()->vrouter_server_ip(),
241 #else
242  boost::asio::local::stream_protocol::socket
243  socket(*(ksync_->agent()->event_manager()->io_service()));
244  boost::asio::local::stream_protocol::endpoint
245  endpoint(ksync_agent_vrouter_sock_path);
246 #endif
247  boost::system::error_code ec;
248  socket.connect(endpoint, ec);
249  if (ec) {
250  assert(0);
251  }
252 
253  socket.send(boost::asio::buffer(cl->cl_buf, cl->cl_buf_offset), 0, ec);
254  if (ec) {
255  assert(0);
256  }
257 
258  uint32_t len_read = 0;
259  uint32_t data_len = sizeof(struct nlmsghdr);
260  while (len_read < data_len) {
261  len_read = socket.read_some(boost::asio::buffer(cl->cl_buf + len_read,
262  cl->cl_buf_len), ec);
263  if (ec) {
264  assert(0);
265  }
266 
267  if (len_read > sizeof(struct nlmsghdr)) {
268  const struct nlmsghdr *nlh =
269  (const struct nlmsghdr *)((cl->cl_buf));
270  data_len = nlh->nlmsg_len;
271  }
272  }
273 
276  nl_free_client(cl);
277 }
278 
280  GetTableSize();
281  Mmap(false, NULL, false);
282 }
uint32_t audit_idx_
Definition: ksync_memory.h:87
static const uint32_t kAuditYieldTimer
Definition: ksync_memory.h:20
static int GetNetlinkFamilyId()
Definition: ksync_sock.h:393
std::string cat_ksocketdir() const
Definition: agent_param.h:573
static const uint32_t kAuditYieldMin
Definition: ksync_memory.h:26
Agent * agent() const
Definition: ksync_init.h:39
std::string table_path_
Definition: ksync_memory.h:73
#define kTaskFlowAudit
Definition: agent.h:326
virtual void SetTableSize()
Definition: ksync_memory.h:43
virtual int EncodeReq(nl_client *nl, uint32_t attr_len)=0
virtual void UpdateAgentHoldFlowCounter()
Definition: ksync_memory.h:48
virtual bool IsInactiveEntry(uint32_t idx, uint8_t &gen_id)=0
void InitMem(void *hpmem)
Timer * audit_timer_
Definition: ksync_memory.h:82
uint32_t table_entries_count_
Definition: ksync_memory.h:80
boost::asio::io_context * io_service()
Definition: event_manager.h:42
static const int kTestFlowTableSize
Definition: ksync_memory.cc:44
static const uint32_t kAuditSweepTime
Definition: ksync_memory.h:18
uint32_t audit_yield_
Definition: ksync_memory.h:85
static AgentSandeshContext * GetAgentSandeshContext(uint32_t type)
Definition: ksync_sock.h:396
bool AuditProcess()
std::list< AuditEntry > audit_list_
Definition: ksync_memory.h:88
static const uint32_t kAuditYieldMax
Definition: ksync_memory.h:24
virtual void Init()
Definition: ksync_memory.cc:69
virtual void CreateProtoAuditEntry(uint32_t index, uint8_t gen_id)=0
int major_devid_
Definition: ksync_memory.h:75
void Mmap(bool unlink, void *khpmem, bool kernel_mode)
Definition: ksync_memory.cc:87
virtual void Shutdown()
uint32_t audit_interval_
Definition: ksync_memory.h:86
const uint32_t vrouter_server_port() const
Definition: agent.h:973
virtual int get_entry_size()=0
EventManager * event_manager() const
Definition: agent.h:1103
void * table_
Definition: ksync_memory.h:71
virtual void IncrementHoldFlowCounter()
Definition: ksync_memory.h:47
virtual void InitTest()
int minor_devid_
Definition: ksync_memory.h:76
AgentParam * params() const
Definition: agent.h:1218
uint32_t audit_timeout_
Definition: ksync_memory.h:84
#define KSYNC_AGENT_VROUTER_SOCK_PATH
Definition: ksync_sock.h:567
static const uint32_t kAuditTimeout
Definition: ksync_memory.h:22
KSyncMemory(KSync *ksync, uint32_t minor_id)
Definition: ksync_memory.cc:46
static uint64_t UTCTimestampUsec()
Definition: time_util.h:13
virtual ~KSyncMemory()
Definition: ksync_memory.cc:65
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:108
KSync * ksync_
Definition: ksync_memory.h:70
#define LOG(_Level, _Msg)
Definition: logging.h:33
const Ip4Address vrouter_server_ip() const
Definition: agent.h:967
int GetKernelTableSize()
virtual void DecrementHoldFlowCounter()
Definition: ksync_memory.h:46
void GetTableSize()
void MapSharedMemory()
bool cat_is_agent_mocked() const
Definition: agent_param.h:569
static bool DeleteTimer(Timer *Timer)
Definition: timer.cc:222