1/* 2 ************************************************************************** 3 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all copies. 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 ************************************************************************** 15 */ 16 17/* 18 * nss_ipv4.c 19 * NSS IPv4 APIs 20 */ 21#include <linux/sysctl.h> 22#include "nss_tx_rx_common.h" 23 24int nss_ipv4_conn_cfg __read_mostly = NSS_DEFAULT_NUM_CONN; 25static struct nss_conn_cfg_pvt i4cfgp; 26 27/* 28 29 * nss_ipv4_max_conn_count() 30 * Return the maximum number of IPv4 connections that the NSS acceleration engine supports. 31 */ 32int nss_ipv4_max_conn_count(void) 33{ 34 return nss_core_max_ipv4_conn_get(); 35} 36EXPORT_SYMBOL(nss_ipv4_max_conn_count); 37 38/* 39 * nss_ipv4_driver_conn_sync_update() 40 * Update driver specific information from the messsage. 41 */ 42static void nss_ipv4_driver_conn_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync *nirs) 43{ 44 struct nss_top_instance *nss_top = nss_ctx->nss_top; 45 46 /* 47 * Update statistics maintained by NSS driver 48 */ 49 spin_lock_bh(&nss_top->stats_lock); 50 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_PKTS] += nirs->flow_rx_packet_count + nirs->return_rx_packet_count; 51 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_RX_BYTES] += nirs->flow_rx_byte_count + nirs->return_rx_byte_count; 52 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_TX_PKTS] += nirs->flow_tx_packet_count + nirs->return_tx_packet_count; 53 nss_top->stats_ipv4[NSS_STATS_IPV4_ACCELERATED_TX_BYTES] += nirs->flow_tx_byte_count + nirs->return_tx_byte_count; 54 spin_unlock_bh(&nss_top->stats_lock); 55} 56 57/* 58 * nss_ipv4_driver_conn_sync_many_update() 59 * Update driver specific information from the conn_sync_many messsage. 60 */ 61static void nss_ipv4_driver_conn_sync_many_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync_many_msg *nicsm) 62{ 63 int i; 64 65 /* 66 * Sanity check for the stats count 67 */ 68 if (nicsm->count * sizeof(struct nss_ipv4_conn_sync) >= nicsm->size) { 69 nss_warning("%p: stats sync count %u exceeds the size of this msg %u", nss_ctx, nicsm->count, nicsm->size); 70 return; 71 } 72 73 for (i = 0; i < nicsm->count; i++) { 74 nss_ipv4_driver_conn_sync_update(nss_ctx, &nicsm->conn_sync[i]); 75 } 76} 77 78/* 79 * nss_ipv4_driver_node_sync_update) 80 * Update driver specific information from the messsage. 81 */ 82static void nss_ipv4_driver_node_sync_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_node_sync *nins) 83{ 84 struct nss_top_instance *nss_top = nss_ctx->nss_top; 85 uint32_t i; 86 87 /* 88 * Update statistics maintained by NSS driver 89 */ 90 spin_lock_bh(&nss_top->stats_lock); 91 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_PKTS] += nins->node_stats.rx_packets; 92 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_BYTES] += nins->node_stats.rx_bytes; 93 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_RX_DROPPED] += nins->node_stats.rx_dropped; 94 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_PKTS] += nins->node_stats.tx_packets; 95 nss_top->stats_node[NSS_IPV4_RX_INTERFACE][NSS_STATS_NODE_TX_BYTES] += nins->node_stats.tx_bytes; 96 97 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_REQUESTS] += nins->ipv4_connection_create_requests; 98 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_COLLISIONS] += nins->ipv4_connection_create_collisions; 99 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv4_connection_create_invalid_interface; 100 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_connection_destroy_requests; 101 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_DESTROY_MISSES] += nins->ipv4_connection_destroy_misses; 102 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_HASH_HITS] += nins->ipv4_connection_hash_hits; 103 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_HASH_REORDERS] += nins->ipv4_connection_hash_reorders; 104 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_FLUSHES] += nins->ipv4_connection_flushes; 105 nss_top->stats_ipv4[NSS_STATS_IPV4_CONNECTION_EVICTIONS] += nins->ipv4_connection_evictions; 106 nss_top->stats_ipv4[NSS_STATS_IPV4_FRAGMENTATIONS] += nins->ipv4_fragmentations; 107 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_CREATE_REQUESTS] += nins->ipv4_mc_connection_create_requests; 108 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_UPDATE_REQUESTS] += nins->ipv4_mc_connection_update_requests; 109 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_CREATE_INVALID_INTERFACE] += nins->ipv4_mc_connection_create_invalid_interface; 110 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_DESTROY_REQUESTS] += nins->ipv4_mc_connection_destroy_requests; 111 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_DESTROY_MISSES] += nins->ipv4_mc_connection_destroy_misses; 112 nss_top->stats_ipv4[NSS_STATS_IPV4_MC_CONNECTION_FLUSHES] += nins->ipv4_mc_connection_flushes; 113 114 for (i = 0; i < NSS_EXCEPTION_EVENT_IPV4_MAX; i++) { 115 nss_top->stats_if_exception_ipv4[i] += nins->exception_events[i]; 116 } 117 spin_unlock_bh(&nss_top->stats_lock); 118} 119 120/* 121 * nss_ipv4_rx_msg_handler() 122 * Handle NSS -> HLOS messages for IPv4 bridge/route 123 */ 124static void nss_ipv4_rx_msg_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, __attribute__((unused))void *app_data) 125{ 126 struct nss_ipv4_msg *nim = (struct nss_ipv4_msg *)ncm; 127 nss_ipv4_msg_callback_t cb; 128 129 BUG_ON(ncm->interface != NSS_IPV4_RX_INTERFACE); 130 131 /* 132 * Sanity check the message type 133 */ 134 if (ncm->type >= NSS_IPV4_MAX_MSG_TYPES) { 135 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type); 136 return; 137 } 138 139 if (ncm->len > sizeof(struct nss_ipv4_msg)) { 140 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface); 141 return; 142 } 143 144 /* 145 * Log failures 146 */ 147 nss_core_log_msg_failures(nss_ctx, ncm); 148 149 switch (nim->cm.type) { 150 case NSS_IPV4_RX_NODE_STATS_SYNC_MSG: 151 /* 152 * Update driver statistics on node sync. 153 */ 154 nss_ipv4_driver_node_sync_update(nss_ctx, &nim->msg.node_stats); 155 break; 156 157 case NSS_IPV4_RX_CONN_STATS_SYNC_MSG: 158 /* 159 * Update driver statistics on connection sync. 160 */ 161 nss_ipv4_driver_conn_sync_update(nss_ctx, &nim->msg.conn_stats); 162 break; 163 164 case NSS_IPV4_TX_CONN_STATS_SYNC_MANY_MSG: 165 /* 166 * Update driver statistics on connection sync many. 167 */ 168 nss_ipv4_driver_conn_sync_many_update(nss_ctx, &nim->msg.conn_stats_many); 169 break; 170 } 171 172 /* 173 * Update the callback and app_data for NOTIFY messages, IPv4 sends all notify messages 174 * to the same callback/app_data. 175 */ 176 if (nim->cm.response == NSS_CMM_RESPONSE_NOTIFY) { 177 ncm->cb = (uint32_t)nss_ctx->nss_top->ipv4_callback; 178 ncm->app_data = (uint32_t)nss_ctx->nss_top->ipv4_ctx; 179 } 180 181 /* 182 * Do we have a callback? 183 */ 184 if (!ncm->cb) { 185 return; 186 } 187 188 /* 189 * Callback 190 */ 191 cb = (nss_ipv4_msg_callback_t)ncm->cb; 192 cb((void *)ncm->app_data, nim); 193} 194 195/* 196 * nss_ipv4_tx_with_size() 197 * Transmit an ipv4 message to the FW with a specified size. 198 */ 199nss_tx_status_t nss_ipv4_tx_with_size(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim, uint32_t size) 200{ 201 struct nss_ipv4_msg *nim2; 202 struct nss_cmn_msg *ncm = &nim->cm; 203 struct sk_buff *nbuf; 204 int32_t status; 205 206 NSS_VERIFY_CTX_MAGIC(nss_ctx); 207 if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) { 208 nss_warning("%p: ipv4 msg dropped as core not ready", nss_ctx); 209 return NSS_TX_FAILURE_NOT_READY; 210 } 211 212 /* 213 * Sanity check the message 214 */ 215 if (ncm->interface != NSS_IPV4_RX_INTERFACE) { 216 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface); 217 return NSS_TX_FAILURE; 218 } 219 220 if (ncm->type >= NSS_IPV4_MAX_MSG_TYPES) { 221 nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type); 222 return NSS_TX_FAILURE; 223 } 224 225 if (ncm->len > sizeof(struct nss_ipv4_msg)) { 226 nss_warning("%p: tx request for another interface: %d", nss_ctx, ncm->interface); 227 return NSS_TX_FAILURE; 228 } 229 230 if(size > PAGE_SIZE) { 231 nss_warning("%p: tx request size too large: %u", nss_ctx, size); 232 return NSS_TX_FAILURE; 233 } 234 235 nbuf = dev_alloc_skb(size); 236 if (unlikely(!nbuf)) { 237 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]); 238 nss_warning("%p: msg dropped as command allocation failed", nss_ctx); 239 return NSS_TX_FAILURE; 240 } 241 242 /* 243 * Copy the message to our skb. 244 */ 245 nim2 = (struct nss_ipv4_msg *)skb_put(nbuf, sizeof(struct nss_ipv4_msg)); 246 memcpy(nim2, nim, sizeof(struct nss_ipv4_msg)); 247 248 status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0); 249 if (status != NSS_CORE_STATUS_SUCCESS) { 250 dev_kfree_skb_any(nbuf); 251 nss_warning("%p: unable to enqueue IPv4 msg\n", nss_ctx); 252 return NSS_TX_FAILURE; 253 } 254 255 nss_hal_send_interrupt(nss_ctx->nmap, nss_ctx->h2n_desc_rings[NSS_IF_CMD_QUEUE].desc_ring.int_bit, 256 NSS_REGS_H2N_INTR_STATUS_DATA_COMMAND_QUEUE); 257 258 NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]); 259 return NSS_TX_SUCCESS; 260} 261 262/* 263 * nss_ipv4_tx() 264 * Transmit an ipv4 message to the FW. 265 */ 266nss_tx_status_t nss_ipv4_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim) 267{ 268 return nss_ipv4_tx_with_size(nss_ctx, nim, NSS_NBUF_PAYLOAD_SIZE); 269} 270 271/* 272 ********************************** 273 Register/Unregister/Miscellaneous APIs 274 ********************************** 275 */ 276 277/* 278 * nss_ipv4_notify_register() 279 * Register to received IPv4 events. 280 * 281 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv4 on any core? 282 */ 283struct nss_ctx_instance *nss_ipv4_notify_register(nss_ipv4_msg_callback_t cb, void *app_data) 284{ 285 /* 286 * TODO: We need to have a new array in support of the new API 287 * TODO: If we use a per-context array, we would move the array into nss_ctx based. 288 */ 289 nss_top_main.ipv4_callback = cb; 290 nss_top_main.ipv4_ctx = app_data; 291 return &nss_top_main.nss[nss_top_main.ipv4_handler_id]; 292} 293 294/* 295 * nss_ipv4_notify_unregister() 296 * Unregister to received IPv4 events. 297 * 298 * NOTE: Do we want to pass an nss_ctx here so that we can register for ipv4 on any core? 299 */ 300void nss_ipv4_notify_unregister(void) 301{ 302 nss_top_main.ipv4_callback = NULL; 303} 304 305/* 306 * nss_ipv4_get_mgr() 307 * 308 * TODO: This only suppports a single ipv4, do we ever want to support more? 309 */ 310struct nss_ctx_instance *nss_ipv4_get_mgr(void) 311{ 312 return (void *)&nss_top_main.nss[nss_top_main.ipv4_handler_id]; 313} 314 315/* 316 * nss_ipv4_register_handler() 317 * Register our handler to receive messages for this interface 318 */ 319void nss_ipv4_register_handler(void) 320{ 321 if (nss_core_register_handler(NSS_IPV4_RX_INTERFACE, nss_ipv4_rx_msg_handler, NULL) != NSS_CORE_STATUS_SUCCESS) { 322 nss_warning("IPv4 handler failed to register"); 323 } 324} 325 326/* 327 * nss_ipv4_conn_cfg_process() 328 * Process request to configure number of ipv4 connections 329 */ 330static int nss_ipv4_conn_cfg_process(struct nss_ctx_instance *nss_ctx, int conn, 331 void (*cfg_cb)(void *app_data, struct nss_ipv4_msg *nim)) 332{ 333 struct nss_ipv4_msg nim; 334 struct nss_ipv4_rule_conn_cfg_msg *nirccm; 335 nss_tx_status_t nss_tx_status; 336 uint32_t sum_of_conn; 337 338 /* 339 * The input should be multiple of 1024. 340 * Input for ipv4 and ipv6 sum together should not exceed 8k 341 * Min. value should be at least 256 connections. This is the 342 * minimum connections we will support for each of them. 343 */ 344 sum_of_conn = conn + nss_ipv6_conn_cfg; 345 if ((conn & NSS_NUM_CONN_QUANTA_MASK) || 346 (sum_of_conn > NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6) || 347 (conn < NSS_MIN_NUM_CONN)) { 348 nss_warning("%p: input supported connections (%d) does not adhere\ 349 specifications\n1) not multiple of 1024,\n2) is less than \ 350 min val: %d, OR\n IPv4/6 total exceeds %d\n", 351 nss_ctx, 352 conn, 353 NSS_MIN_NUM_CONN, 354 NSS_MAX_TOTAL_NUM_CONN_IPV4_IPV6); 355 return -EINVAL; 356 } 357 358 nss_info("%p: IPv4 supported connections: %d\n", nss_ctx, conn); 359 360 memset(&nim, 0, sizeof(struct nss_ipv4_msg)); 361 nss_ipv4_msg_init(&nim, NSS_IPV4_RX_INTERFACE, NSS_IPV4_TX_CONN_CFG_RULE_MSG, 362 sizeof(struct nss_ipv4_rule_conn_cfg_msg), cfg_cb, NULL); 363 364 nirccm = &nim.msg.rule_conn_cfg; 365 nirccm->num_conn = htonl(conn); 366 nss_tx_status = nss_ipv4_tx(nss_ctx, &nim); 367 368 if (nss_tx_status != NSS_TX_SUCCESS) { 369 nss_warning("%p: nss_tx error setting IPv4 Connections: %d\n", 370 nss_ctx, 371 conn); 372 return -EIO; 373 } 374 375 return 0; 376} 377 378/* 379 * nss_ipv4_conn_cfg_callback() 380 * call back function for the ipv4 connection configuration handler 381 */ 382static void nss_ipv4_conn_cfg_callback(void *app_data, struct nss_ipv4_msg *nim) 383{ 384 385 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) { 386 nss_warning("IPv4 connection configuration failed with error: %d\n", nim->cm.error); 387 /* 388 * Error, hence we are not updating the nss_ipv4_conn_cfg 389 * Restore the current_value to its previous state 390 */ 391 i4cfgp.response = NSS_FAILURE; 392 complete(&i4cfgp.complete); 393 return; 394 } 395 396 /* 397 * Sucess at NSS FW, hence updating nss_ipv4_conn_cfg, with the valid value 398 * saved at the sysctl handler. 399 */ 400 nss_info("IPv4 connection configuration success: %d\n", nim->cm.error); 401 i4cfgp.response = NSS_SUCCESS; 402 complete(&i4cfgp.complete); 403} 404 405/* 406 * nss_ipv4_conn_cfg_handler() 407 * Sets the number of connections for IPv4 408 */ 409static int nss_ipv4_conn_cfg_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) 410{ 411 struct nss_top_instance *nss_top = &nss_top_main; 412 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; 413 int ret = NSS_FAILURE; 414 415 /* 416 * Acquiring semaphore 417 */ 418 down(&i4cfgp.sem); 419 420 /* 421 * Take snap shot of current value 422 */ 423 i4cfgp.current_value = nss_ipv4_conn_cfg; 424 425 /* 426 * Write the variable with user input 427 */ 428 ret = proc_dointvec(ctl, write, buffer, lenp, ppos); 429 if (ret || (!write)) { 430 up(&i4cfgp.sem); 431 return ret; 432 } 433 434 /* 435 * Process request to change number of IPv4 connections 436 */ 437 ret = nss_ipv4_conn_cfg_process(nss_ctx, nss_ipv4_conn_cfg, nss_ipv4_conn_cfg_callback); 438 if (ret != 0) { 439 goto failure; 440 } 441 442 /* 443 * Blocking call, wait till we get ACK for this msg. 444 */ 445 ret = wait_for_completion_timeout(&i4cfgp.complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT)); 446 if (ret == 0) { 447 nss_warning("%p: Waiting for ack timed out\n", nss_ctx); 448 goto failure; 449 } 450 451 /* 452 * ACK/NACK received from NSS FW 453 * If ACK: Callback function will update nss_ipv4_conn_cfg with 454 * i4cfgp.num_conn_valid, which holds the user input 455 */ 456 if (NSS_FAILURE == i4cfgp.response) { 457 goto failure; 458 } 459 460 up(&i4cfgp.sem); 461 return 0; 462 463failure: 464 /* 465 * Restore the current_value to its previous state 466 */ 467 nss_ipv4_conn_cfg = i4cfgp.current_value; 468 up(&i4cfgp.sem); 469 return -EINVAL; 470} 471 472/* 473 * nss_ipv4_update_conn_count_cb() 474 * call back function for the ipv4 connection count update handler 475 */ 476static void nss_ipv4_update_conn_count_cb(void *app_data, struct nss_ipv4_msg *nim) 477{ 478 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) { 479 nss_warning("IPv4 connection count update failed with error: %d\n", nim->cm.error); 480 return; 481 } 482 483 nss_warning("IPv4 connection count update success: %d\n", nim->cm.error); 484} 485 486/* 487 * nss_ipv4_update_conn_count() 488 * Sets the maximum number of connections for IPv4 489 */ 490int nss_ipv4_update_conn_count(int ipv4_num_conn) 491{ 492 struct nss_top_instance *nss_top = &nss_top_main; 493 struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; 494 int saved_nss_ipv4_conn_cfg = nss_ipv4_conn_cfg; 495 int ret = 0; 496 497 nss_ipv4_conn_cfg = ipv4_num_conn; 498 499 /* 500 * Process request to change number of IPv4 connections 501 */ 502 ret = nss_ipv4_conn_cfg_process(nss_ctx, nss_ipv4_conn_cfg, 503 nss_ipv4_update_conn_count_cb); 504 if (ret != 0) { 505 nss_ipv4_conn_cfg = saved_nss_ipv4_conn_cfg; 506 return ret; 507 } 508 509 return 0; 510} 511 512static ctl_table nss_ipv4_table[] = { 513 { 514 .procname = "ipv4_conn", 515 .data = &nss_ipv4_conn_cfg, 516 .maxlen = sizeof(int), 517 .mode = 0644, 518 .proc_handler = &nss_ipv4_conn_cfg_handler, 519 }, 520 { } 521}; 522 523static ctl_table nss_ipv4_dir[] = { 524 { 525 .procname = "ipv4cfg", 526 .mode = 0555, 527 .child = nss_ipv4_table, 528 }, 529 { } 530}; 531 532 533static ctl_table nss_ipv4_root_dir[] = { 534 { 535 .procname = "nss", 536 .mode = 0555, 537 .child = nss_ipv4_dir, 538 }, 539 { } 540}; 541 542static ctl_table nss_ipv4_root[] = { 543 { 544 .procname = "dev", 545 .mode = 0555, 546 .child = nss_ipv4_root_dir, 547 }, 548 { } 549}; 550 551static struct ctl_table_header *nss_ipv4_header; 552 553/* 554 * nss_ipv4_register_sysctl() 555 * Register sysctl specific to ipv4 556 */ 557void nss_ipv4_register_sysctl(void) 558{ 559 /* 560 * Register sysctl table. 561 */ 562 nss_ipv4_header = register_sysctl_table(nss_ipv4_root); 563 sema_init(&i4cfgp.sem, 1); 564 init_completion(&i4cfgp.complete); 565 i4cfgp.current_value = nss_ipv4_conn_cfg; 566} 567 568/* 569 * nss_ipv4_unregister_sysctl() 570 * Unregister sysctl specific to ipv4 571 */ 572void nss_ipv4_unregister_sysctl(void) 573{ 574 /* 575 * Unregister sysctl table. 576 */ 577 if (nss_ipv4_header) { 578 unregister_sysctl_table(nss_ipv4_header); 579 } 580} 581 582/* 583 * nss_ipv4_msg_init() 584 * Initialize IPv4 message. 585 */ 586void nss_ipv4_msg_init(struct nss_ipv4_msg *nim, uint16_t if_num, uint32_t type, uint32_t len, 587 nss_ipv4_msg_callback_t cb, void *app_data) 588{ 589 nss_cmn_msg_init(&nim->cm, if_num, type, len, (void *)cb, app_data); 590} 591 592EXPORT_SYMBOL(nss_ipv4_tx); 593EXPORT_SYMBOL(nss_ipv4_tx_with_size); 594EXPORT_SYMBOL(nss_ipv4_notify_register); 595EXPORT_SYMBOL(nss_ipv4_notify_unregister); 596EXPORT_SYMBOL(nss_ipv4_get_mgr); 597EXPORT_SYMBOL(nss_ipv4_register_sysctl); 598EXPORT_SYMBOL(nss_ipv4_unregister_sysctl); 599EXPORT_SYMBOL(nss_ipv4_msg_init); 600EXPORT_SYMBOL(nss_ipv4_update_conn_count); 601