1/* 2 ************************************************************************** 3 * Copyright (c) 2014-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#include <linux/version.h> 18#include <linux/types.h> 19#include <linux/ip.h> 20#include <linux/tcp.h> 21#include <linux/module.h> 22#include <linux/skbuff.h> 23#include <linux/icmp.h> 24#include <linux/debugfs.h> 25#include <linux/kthread.h> 26#include <linux/pkt_sched.h> 27#include <linux/string.h> 28#include <net/ip6_route.h> 29#include <net/ip6_fib.h> 30#include <net/addrconf.h> 31#include <net/ipv6.h> 32#include <net/tcp.h> 33#include <asm/unaligned.h> 34#include <asm/uaccess.h> /* for put_user */ 35#include <net/ipv6.h> 36#include <linux/inet.h> 37#include <linux/in6.h> 38#include <linux/udp.h> 39#include <linux/tcp.h> 40#include <linux/ppp_defs.h> 41#include <linux/mroute6.h> 42#include <linux/vmalloc.h> 43 44#include <linux/inetdevice.h> 45#include <linux/if_arp.h> 46#include <linux/netfilter_ipv6.h> 47#include <linux/netfilter_bridge.h> 48#include <linux/if_bridge.h> 49#include <net/arp.h> 50#include <net/netfilter/nf_conntrack.h> 51#include <net/netfilter/nf_conntrack_acct.h> 52#include <net/netfilter/nf_conntrack_helper.h> 53#include <net/netfilter/nf_conntrack_l4proto.h> 54#include <net/netfilter/nf_conntrack_l3proto.h> 55#include <net/netfilter/nf_conntrack_zones.h> 56#include <net/netfilter/nf_conntrack_core.h> 57#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 58#include <net/netfilter/ipv6/nf_defrag_ipv6.h> 59#ifdef ECM_INTERFACE_VLAN_ENABLE 60#include <linux/../../net/8021q/vlan.h> 61#include <linux/if_vlan.h> 62#endif 63 64/* 65 * Debug output levels 66 * 0 = OFF 67 * 1 = ASSERTS / ERRORS 68 * 2 = 1 + WARN 69 * 3 = 2 + INFO 70 * 4 = 3 + TRACE 71 */ 72#define DEBUG_LEVEL ECM_NSS_MULTICAST_IPV6_DEBUG_LEVEL 73 74#include <nss_api_if.h> 75#include <mc_ecm.h> 76 77#include "ecm_types.h" 78#include "ecm_db_types.h" 79#include "ecm_state.h" 80#include "ecm_tracker.h" 81#include "ecm_classifier.h" 82#include "ecm_front_end_types.h" 83#include "ecm_tracker_datagram.h" 84#include "ecm_tracker_udp.h" 85#include "ecm_tracker_tcp.h" 86#include "ecm_db.h" 87#include "ecm_classifier_default.h" 88#include "ecm_interface.h" 89#include "ecm_nss_ipv6.h" 90#include "ecm_nss_multicast_ipv6.h" 91#include "ecm_nss_common.h" 92 93/* 94 * Magic numbers 95 */ 96#define ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC 0xED13 97 98/* 99 * struct ecm_nss_ipv6_multicast_connection_instance 100 * A connection specific front end instance for MULTICAST connections 101 */ 102struct ecm_nss_multicast_ipv6_connection_instance { 103 struct ecm_front_end_connection_instance base; /* Base class */ 104#if (DEBUG_LEVEL > 0) 105 uint16_t magic; 106#endif 107}; 108 109static int ecm_nss_multicast_ipv6_accelerated_count = 0; 110 /* Number of IPv6 multicast connections currently offloaded */ 111 112/* 113 * ecm_nss_multicast_ipv6_interface_heirarchy_construct() 114 * Create destination multicast interface heirachy for Route/Bridge connection flow 115 */ 116static int ecm_nss_multicast_ipv6_interface_heirarchy_construct(struct ecm_front_end_connection_instance *feci, 117 struct ecm_db_iface_instance *interfaces, struct net_device *in_dev, 118 struct net_device *brdev, ip_addr_t packet_src_addr, ip_addr_t packet_dest_addr, uint8_t max_if, 119 uint32_t *dst_dev, int32_t *to_interface_first, uint8_t *src_node_addr, bool is_routed) 120{ 121 int32_t iface_instance_cnt; 122 123 if (is_routed) { 124 iface_instance_cnt = ecm_interface_multicast_heirarchy_construct_routed(feci, interfaces, in_dev, packet_src_addr, packet_dest_addr, max_if, dst_dev, to_interface_first, NULL); 125 } else { 126 iface_instance_cnt = ecm_interface_multicast_heirarchy_construct_bridged(feci, interfaces, brdev, 127 packet_src_addr, packet_dest_addr, max_if, 128 dst_dev, to_interface_first, src_node_addr, NULL); 129 } 130 return iface_instance_cnt; 131} 132 133/* 134 * ecm_nss_multicast_ipv6_connection_update_callback() 135 * Callback for handling Ack/Nack for update accelerate rules. 136 */ 137static void ecm_nss_multicast_ipv6_connection_update_callback(void *app_data, struct nss_ipv6_msg *nim) 138{ 139 struct nss_ipv6_mc_rule_create_msg *nircm = &nim->msg.mc_rule_create; 140 uint32_t serial = (uint32_t)app_data; 141 struct ecm_db_connection_instance *ci; 142 struct ecm_front_end_connection_instance *feci; 143 struct ecm_nss_multicast_ipv6_connection_instance *nmci; 144 //ip_addr_t flow_ip; 145 //ip_addr_t return_ip; 146 147 /*TODO: If the response is NACK then decelerate the flow and flushes all rules */ 148 DEBUG_TRACE("%p: update callback, response received from FW : %u\n", nim, nim->cm.response); 149 150 /* 151 * Is this a response to a create message? 152 */ 153 if (nim->cm.type != NSS_IPV6_TX_CREATE_MC_RULE_MSG) { 154 DEBUG_ERROR("%p: multicast update callback with improper type: %d, serial: %u\n", nim, nim->cm.type, serial); 155 return; 156 } 157 158 /* 159 * Is this a response to a update rule message? 160 */ 161 if ( !(nircm->rule_flags & NSS_IPV6_MC_RULE_CREATE_FLAG_MC_UPDATE)) { 162 DEBUG_ERROR("%p: multicast update callback with improper type: %d, serial: %u\n", nim, nim->cm.type, serial); 163 return; 164 } 165 166 /* 167 * Look up ecm connection so that we can update the status. 168 */ 169 ci = ecm_db_connection_serial_find_and_ref(serial); 170 if (!ci) { 171 DEBUG_TRACE("%p: multicast update callback, connection not found, serial: %u\n", nim, serial); 172 return; 173 } 174 175 /* 176 * Release ref held for this ack/nack response. 177 * NOTE: It's okay to do this here, ci won't go away, because the ci is held as 178 * a result of the ecm_db_connection_serial_find_and_ref() 179 */ 180 ecm_db_connection_deref(ci); 181 182 /* 183 * Get the front end instance 184 */ 185 feci = ecm_db_connection_front_end_get_and_ref(ci); 186 nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 187 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 188 189 /* 190 * Dump some useful trace information. 191 */ 192 DEBUG_TRACE("%p: Update accelerate response for connection: %p, serial: %u\n", nmci, feci->ci, serial); 193 DEBUG_TRACE("%p: valid_flags: %x\n", nmci, nircm->valid_flags); 194 //DEBUG_TRACE("%p: flow_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(flow_ip), nircm->tuple.flow_ident); 195 //DEBUG_TRACE("%p: return_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(return_ip), nircm->tuple.return_ident); 196 DEBUG_TRACE("%p: protocol: %d\n", nmci, nircm->tuple.protocol); 197 198 /* 199 * Release the connection. 200 */ 201 feci->deref(feci); 202 ecm_db_connection_deref(ci); 203 return; 204} 205 206/* 207 * ecm_nss_multicast_ipv6_connection_create_callback() 208 * callback for handling create ack/nack calls for multicast create commands. 209 */ 210static void ecm_nss_multicast_ipv6_connection_create_callback(void *app_data, struct nss_ipv6_msg *nim) 211{ 212 struct nss_ipv6_mc_rule_create_msg *__attribute__((unused))nircm = &nim->msg.mc_rule_create; 213 uint32_t serial = (uint32_t)app_data; 214 struct ecm_db_connection_instance *ci; 215 struct ecm_front_end_connection_instance *feci; 216 struct ecm_nss_multicast_ipv6_connection_instance *nmci; 217 ip_addr_t flow_ip; 218 ip_addr_t return_ip; 219 220 /* 221 * Is this a response to a create message? 222 */ 223 if (nim->cm.type != NSS_IPV6_TX_CREATE_MC_RULE_MSG) { 224 DEBUG_ERROR("%p: udp create callback with improper type: %d, serial: %u\n", nim, nim->cm.type, serial); 225 return; 226 } 227 228 /* 229 * Look up ecm connection so that we can update the status. 230 */ 231 ci = ecm_db_connection_serial_find_and_ref(serial); 232 if (!ci) { 233 DEBUG_TRACE("%p: create callback, connection not found, serial: %u\n", nim, serial); 234 return; 235 } 236 237 /* 238 * Release ref held for this ack/nack response. 239 * NOTE: It's okay to do this here, ci won't go away, because the ci is held as 240 * a result of the ecm_db_connection_serial_find_and_ref() 241 */ 242 ecm_db_connection_deref(ci); 243 244 /* 245 * Get the front end instance 246 */ 247 feci = ecm_db_connection_front_end_get_and_ref(ci); 248 nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 249 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 250 251 ECM_NSS_IPV6_ADDR_TO_IP_ADDR(flow_ip, nircm->tuple.flow_ip); 252 ECM_NSS_IPV6_ADDR_TO_IP_ADDR(return_ip, nircm->tuple.return_ip); 253 254 /* 255 * Dump some useful trace information. 256 */ 257 DEBUG_TRACE("%p: accelerate response for connection: %p, serial: %u\n", nmci, feci->ci, serial); 258 DEBUG_TRACE("%p: rule_flags: %x, valid_flags: %x\n", nmci, nircm->rule_flags, nircm->valid_flags); 259 DEBUG_TRACE("%p: flow_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(flow_ip), nircm->tuple.flow_ident); 260 DEBUG_TRACE("%p: return_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(return_ip), nircm->tuple.return_ident); 261 DEBUG_TRACE("%p: protocol: %d\n", nmci, nircm->tuple.protocol); 262 263 /* 264 * Handle the creation result code. 265 */ 266 DEBUG_TRACE("%p: response: %d\n", nmci, nim->cm.response); 267 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) { 268 /* 269 * Creation command failed (specific reason ignored). 270 */ 271 DEBUG_TRACE("%p: accel nack: %d\n", nmci, nim->cm.error); 272 spin_lock_bh(&feci->lock); 273 DEBUG_ASSERT(feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING, "%p: Unexpected mode: %d\n", ci, feci->accel_mode); 274 feci->stats.ae_nack++; 275 feci->stats.ae_nack_total++; 276 if (nmci->base.stats.ae_nack >= nmci->base.stats.ae_nack_limit) { 277 /* 278 * Too many NSS rejections 279 */ 280 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_ACCEL_ENGINE; 281 } else { 282 /* 283 * Revert to decelerated 284 */ 285 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL; 286 } 287 288 /* 289 * Clear any decelerate pending flag since we aren't accelerated anyway we can just clear this whether it is set or not 290 */ 291 nmci->base.stats.decelerate_pending = false; 292 293 /* 294 * If connection is now defunct then set mode to ensure no further accel attempts occur 295 */ 296 if (feci->is_defunct) { 297 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DEFUNCT; 298 } 299 spin_unlock_bh(&feci->lock); 300 301 /* 302 * Release the connection. 303 */ 304 feci->deref(feci); 305 ecm_db_connection_deref(ci); 306 return; 307 } 308 309 spin_lock_bh(&feci->lock); 310 DEBUG_ASSERT(feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING, "%p: Unexpected mode: %d\n", ci, feci->accel_mode); 311 312 /* 313 * If a flush occured before we got the ACK then our acceleration was effectively cancelled on us 314 * GGG TODO This is a workaround for a NSS message OOO quirk, this should eventually be removed. 315 */ 316 if (nmci->base.stats.flush_happened) { 317 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL; 318 nmci->base.stats.flush_happened = false; 319 320 /* 321 * We are decelerated, clear any pending flag as that is meaningless now. 322 */ 323 nmci->base.stats.decelerate_pending = false; 324 325 /* 326 * Increement the no-action counter. Our connectin was decelerated on us with no action occurring. 327 */ 328 nmci->base.stats.no_action_seen++; 329 spin_unlock_bh(&feci->lock); 330 331 /* 332 * Release the connection. 333 */ 334 feci->deref(feci); 335 ecm_db_connection_deref(ci); 336 return; 337 } 338 339 /* 340 * We got an ACK - we are accelerated. 341 */ 342 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_ACCEL; 343 344 /* 345 * Create succeeded, declare that we are accelerated. 346 */ 347 spin_lock_bh(&ecm_nss_ipv6_lock); 348 ecm_nss_multicast_ipv6_accelerated_count++; /* Protocol specific counter */ 349 ecm_nss_ipv6_accelerated_count++; /* General running counter */ 350 spin_unlock_bh(&ecm_nss_ipv6_lock); 351 352 /* 353 * Clear any nack count 354 */ 355 nmci->base.stats.ae_nack = 0; 356 357 /* 358 * Decelerate may have been attempted while we were accel pending. 359 * If decelerate is pending then we need to begin deceleration :-( 360 */ 361 if (!nmci->base.stats.decelerate_pending) { 362 363 /* 364 * Increement the no-action counter, this is reset if offload action is seen 365 */ 366 nmci->base.stats.no_action_seen++; 367 368 spin_unlock_bh(&feci->lock); 369 370 /* 371 * Release the connection. 372 */ 373 feci->deref(feci); 374 ecm_db_connection_deref(ci); 375 return; 376 } 377 378 DEBUG_INFO("%p: Decelerate was pending\n", ci); 379 nmci->base.stats.decelerate_pending = false; 380 spin_unlock_bh(&feci->lock); 381 382 feci->decelerate(feci); 383 384 /* 385 * Release the connection. 386 */ 387 feci->deref(feci); 388 ecm_db_connection_deref(ci); 389} 390 391/* 392 * ecm_nss_multicast_ipv6_connection_update_accelerate() 393 * Push destination interface list updates for a multicast connection 394 * to NSS 395 * 396 * This function receives a list of interfaces that have either left or joined the connection, 397 * and sends a 'multicast update' command to NSS to inform about these interface state changes. 398 */ 399static int ecm_nss_multicast_ipv6_connection_update_accelerate(struct ecm_front_end_connection_instance *feci, 400 struct ecm_multicast_if_update *rp) 401{ 402 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 403 uint16_t regen_occurrances; 404 struct ecm_db_iface_instance *to_ifaces; 405 struct ecm_db_iface_instance *ii_temp; 406 struct ecm_db_iface_instance *ii_single; 407 struct ecm_db_iface_instance **ifaces; 408 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX]; 409 struct ecm_db_iface_instance *from_nss_iface; 410 int32_t *to_ifaces_first; 411 int32_t *to_ii_first; 412 struct nss_ipv6_msg *nim; 413 struct nss_ipv6_mc_rule_create_msg *create; 414 ip_addr_t addr; 415 ecm_db_iface_type_t from_iface_type = ECM_DB_IFACE_TYPE_COUNT; 416 ecm_db_iface_type_t to_iface_type = ECM_DB_IFACE_TYPE_COUNT; 417 int32_t ret, vif; 418 int32_t valid_vif_idx = 0; 419 int32_t from_ifaces_first; 420 int32_t to_nss_iface_id = 0; 421 int32_t from_nss_iface_id = 0; 422 uint8_t to_nss_iface_address[ETH_ALEN]; 423 nss_tx_status_t nss_tx_status; 424 int32_t list_index; 425 int32_t to_mtu = 0; 426 int32_t interface_type_counts[ECM_DB_IFACE_TYPE_COUNT]; 427 bool rule_invalid; 428 uint8_t dest_mac[ETH_ALEN]; 429 int from_iface_identifier = 0; 430 int to_iface_bridge_identifier = 0; 431 432 DEBUG_INFO("%p: UPDATE Accel conn: %p\n", nmci, feci->ci); 433 434 /* 435 * Get the re-generation occurrance counter of the connection. 436 * We compare it again at the end - to ensure that the rule construction has seen no generation 437 * changes during rule creation. 438 */ 439 regen_occurrances = ecm_db_connection_regeneration_occurrances_get(feci->ci); 440 441 nim = (struct nss_ipv6_msg *)vzalloc(sizeof(struct nss_ipv6_msg)); 442 if (!nim) { 443 return -1; 444 } 445 446 nss_ipv6_msg_init(nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_CREATE_MC_RULE_MSG, 447 sizeof(struct nss_ipv6_mc_rule_create_msg), 448 ecm_nss_multicast_ipv6_connection_update_callback, 449 (void *)ecm_db_connection_serial_get(feci->ci)); 450 451 create = &nim->msg.mc_rule_create; 452 453 /* 454 * Construct an accel command. 455 */ 456 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(feci->ci, &to_ifaces, &to_ifaces_first); 457 if (ret == 0) { 458 DEBUG_WARN("%p: Accel attempt failed - no interfaces in to_interfaces list!\n", nmci); 459 vfree(nim); 460 return -1; 461 } 462 463 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(feci->ci, from_ifaces); 464 if (from_ifaces_first == ECM_DB_IFACE_HEIRARCHY_MAX) { 465 DEBUG_WARN("%p: Accel attempt failed - no interfaces in from_interfaces list!\n", nmci); 466 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first); 467 vfree(nim); 468 return -1; 469 } 470 471 create->ingress_vlan_tag[0] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED; 472 create->ingress_vlan_tag[1] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED; 473 474 /* 475 * Set the source NSS interface identifier 476 */ 477 from_nss_iface = from_ifaces[from_ifaces_first]; 478 from_nss_iface_id = ecm_db_iface_ae_interface_identifier_get(from_nss_iface); 479 if (from_nss_iface_id < 0) { 480 DEBUG_TRACE("%p: from_nss_iface_id: %d\n", nmci, from_nss_iface_id); 481 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first); 482 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first); 483 vfree(nim); 484 return -1; 485 } 486 487 create->src_interface_num = from_nss_iface_id; 488 from_nss_iface = from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX - 1]; 489 from_iface_type = ecm_db_connection_iface_type_get(from_nss_iface); 490 from_iface_identifier = ecm_db_iface_interface_identifier_get(from_nss_iface); 491 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first); 492 493 /* 494 * Now examine the TO / DEST heirarchy list to construct the destination interface 495 * information 496 */ 497 DEBUG_TRACE("%p: Examine to/dest heirarchy list\n", nmci); 498 rule_invalid = false; 499 500 /* 501 * Loop through the list of interface updates 502 */ 503 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 504#ifdef ECM_INTERFACE_VLAN_ENABLE 505 create->if_rule[vif].egress_vlan_tag[0] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED; 506 create->if_rule[vif].egress_vlan_tag[1] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED; 507#endif 508 /* 509 * If there is no state change for an interface at this index, 510 * then ignore 511 */ 512 if (!(rp->if_join_idx[vif] || rp->if_leave_idx[vif])) { 513 continue; 514 } 515 516 ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, vif); 517 518 /* 519 * We have an update for this interface. Construct the interface information 520 */ 521 to_nss_iface_id = -1; 522 to_iface_type = ECM_DB_IFACE_TYPE_COUNT; 523 memset(interface_type_counts, 0, sizeof(interface_type_counts)); 524 to_ii_first = ecm_db_multicast_if_first_get_at_index(to_ifaces_first, vif); 525 526 for (list_index = *to_ii_first; !rule_invalid && (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) { 527 struct ecm_db_iface_instance *ii; 528 ecm_db_iface_type_t ii_type; 529 char *ii_name; 530 531 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, list_index); 532 ifaces = (struct ecm_db_iface_instance **)ii_single; 533 ii = *ifaces; 534 ii_type = ecm_db_connection_iface_type_get(ii); 535 ii_name = ecm_db_interface_type_to_string(ii_type); 536 DEBUG_TRACE("%p: list_index: %d, ii: %p, type: %d (%s)\n", nmci, list_index, ii, ii_type, ii_name); 537 538 /* 539 * Extract information from this interface type if it is applicable to the rule. 540 * Conflicting information may cause accel to be unsupported. 541 */ 542 switch (ii_type) { 543#ifdef ECM_INTERFACE_PPP_ENABLE 544 struct ecm_db_interface_info_pppoe pppoe_info; 545#endif 546#ifdef ECM_INTERFACE_VLAN_ENABLE 547 struct ecm_db_interface_info_vlan vlan_info; 548#endif 549 550 case ECM_DB_IFACE_TYPE_BRIDGE: 551 DEBUG_TRACE("%p: Bridge\n", nmci); 552 if (interface_type_counts[ii_type] != 0) { 553 /* 554 * Cannot cascade bridges 555 */ 556 rule_invalid = true; 557 DEBUG_TRACE("%p: Bridge - ignore additional\n", nmci); 558 break; 559 } 560 561 ecm_db_iface_bridge_address_get(ii, to_nss_iface_address); 562 to_iface_type = ECM_DB_IFACE_TYPE_BRIDGE; 563 to_iface_bridge_identifier = ecm_db_iface_interface_identifier_get(ii); 564 DEBUG_TRACE("%p: Bridge - mac: %pM\n", nmci, to_nss_iface_address); 565 break; 566 case ECM_DB_IFACE_TYPE_ETHERNET: 567 DEBUG_TRACE("%p: Ethernet\n", nmci); 568 if (interface_type_counts[ii_type] != 0) { 569 570 /* 571 * Ignore additional mac addresses, these are usually as a result of address propagation 572 * from bridges down to ports etc. */ 573 574 DEBUG_TRACE("%p: Ethernet - ignore additional\n", nmci); 575 break; 576 } 577 578 /* 579 * Can only handle one MAC, the first outermost mac. 580 */ 581 ecm_db_iface_ethernet_address_get(ii, to_nss_iface_address); 582 to_mtu = (uint32_t)ecm_db_connection_to_iface_mtu_get(feci->ci); 583 to_nss_iface_id = ecm_db_iface_ae_interface_identifier_get(ii); 584 if (to_nss_iface_id < 0) { 585 DEBUG_TRACE("%p: to_nss_iface_id: %d\n", nmci, to_nss_iface_id); 586 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first); 587 vfree(nim); 588 return -1; 589 } 590 591 DEBUG_TRACE("%p: Ethernet - mac: %pM\n", nmci, to_nss_iface_address); 592 break; 593 case ECM_DB_IFACE_TYPE_PPPOE: 594#ifdef ECM_INTERFACE_PPP_ENABLE 595 /* 596 * More than one PPPoE in the list is not valid! 597 */ 598 if (interface_type_counts[ii_type] != 0) { 599 DEBUG_TRACE("%p: PPPoE - additional unsupported\n", nmci); 600 rule_invalid = true; 601 break; 602 } 603 604 /* 605 * Copy pppoe session info to the creation structure. 606 */ 607 ecm_db_iface_pppoe_session_info_get(ii, &pppoe_info); 608 create->if_rule[valid_vif_idx].pppoe_session_id = pppoe_info.pppoe_session_id; 609 memcpy(create->if_rule[valid_vif_idx].pppoe_remote_mac, pppoe_info.remote_mac, ETH_ALEN); 610 611 DEBUG_TRACE("%p: PPPoE - session: %x, mac: %pM\n", nmci, create->if_rule[valid_vif_idx].pppoe_session_id, create->if_rule[valid_vif_idx].pppoe_remote_mac); 612#else 613 DEBUG_TRACE("%p: PPPoE - unsupported\n", nmci); 614 rule_invalid = true; 615#endif 616 break; 617 case ECM_DB_IFACE_TYPE_VLAN: 618#ifdef ECM_INTERFACE_VLAN_ENABLE 619 DEBUG_TRACE("%p: VLAN\n", nmci); 620 if (interface_type_counts[ii_type] > 1) { 621 622 /* 623 * Can only support two vlans 624 */ 625 rule_invalid = true; 626 DEBUG_TRACE("%p: VLAN - additional unsupported\n", nmci); 627 break; 628 } 629 ecm_db_iface_vlan_info_get(ii, &vlan_info); 630 create->if_rule[valid_vif_idx].egress_vlan_tag[interface_type_counts[ii_type]] = ((vlan_info.vlan_tpid << 16) | vlan_info.vlan_tag); 631 632 /* 633 * If we have not yet got an ethernet mac then take this one (very unlikely as mac should have been propagated to the slave (outer) device 634 */ 635 if (interface_type_counts[ECM_DB_IFACE_TYPE_ETHERNET] == 0) { 636 memcpy(to_nss_iface_address, vlan_info.address, ETH_ALEN); 637 interface_type_counts[ECM_DB_IFACE_TYPE_ETHERNET]++; 638 DEBUG_TRACE("%p: VLAN use mac: %pM\n", nmci, to_nss_iface_address); 639 } 640 create->if_rule[valid_vif_idx].valid_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_VLAN_VALID; 641 DEBUG_TRACE("%p: vlan tag: %x\n", nmci, create->if_rule[valid_vif_idx].egress_vlan_tag[interface_type_counts[ii_type]]); 642#else 643 rule_invalid = true; 644 DEBUG_TRACE("%p: VLAN - unsupported\n", nmci); 645#endif 646 break; 647 default: 648 DEBUG_TRACE("%p: Ignoring: %d (%s)\n", nmci, ii_type, ii_name); 649 } 650 651 /* 652 * Seen an interface of this type 653 */ 654 interface_type_counts[ii_type]++; 655 } 656 657 if (rule_invalid) { 658 DEBUG_WARN("%p: to/dest Rule invalid\n", nmci); 659 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first); 660 vfree(nim); 661 return -1; 662 } 663 664 /* 665 * Is this a valid interface? 666 */ 667 if (to_nss_iface_id != -1) { 668 bool is_bridge; 669 create->if_rule[valid_vif_idx].if_num = to_nss_iface_id; 670 create->if_rule[valid_vif_idx].if_mtu = to_mtu; 671 if (rp->if_join_idx[vif]) { 672 673 /* 674 * The interface has joined the group 675 */ 676 create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_JOIN; 677 } else if (rp->if_leave_idx[vif]) { 678 679 /* 680 * The interface has left the group 681 */ 682 create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_LEAVE; 683 } 684 685 is_bridge = !ecm_db_connection_is_routed_get(feci->ci); 686 687 /* 688 * Do not set the ROUTED flag for pure bridged interfaces 689 */ 690 if (((from_iface_type == ECM_DB_IFACE_TYPE_BRIDGE && 691 to_iface_type == ECM_DB_IFACE_TYPE_BRIDGE) || is_bridge) && 692 (to_iface_bridge_identifier == from_iface_identifier)) { 693 uint8_t from_nss_iface_address[ETH_ALEN]; 694 ecm_db_connection_from_node_address_get(feci->ci, (uint8_t *)from_nss_iface_address); 695 memcpy(create->if_rule[valid_vif_idx].if_mac, from_nss_iface_address, ETH_ALEN); 696 create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_BRIDGE_FLOW; 697 } else { 698 memcpy(create->if_rule[valid_vif_idx].if_mac, to_nss_iface_address, ETH_ALEN); 699 create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_ROUTED_FLOW; 700 } 701 702 valid_vif_idx++; 703 } 704 } 705 706 /* 707 * Set number of interface updates in the update rule 708 */ 709 create->if_count = valid_vif_idx; 710 711 /* 712 * Set the UPDATE flag 713 */ 714 create->rule_flags |= NSS_IPV6_MC_RULE_CREATE_FLAG_MC_UPDATE; 715 716 /* 717 * Set protocol 718 */ 719 create->tuple.protocol = IPPROTO_UDP; 720 721 /* 722 * The src_ip is where the connection established from 723 */ 724 ecm_db_connection_from_address_get(feci->ci, addr); 725 ECM_IP_ADDR_TO_NSS_IPV6_ADDR(create->tuple.flow_ip, addr); 726 727 728 /* 729 * The destination address is what the destination IP is translated to as it is forwarded to the next interface. 730 * For egress this would yield the normal wan host and for ingress this would correctly NAT back to the LAN host 731 */ 732 ecm_db_connection_to_address_get(feci->ci, addr); 733 ECM_IP_ADDR_TO_NSS_IPV6_ADDR(create->tuple.return_ip, addr); 734 735 /* 736 * Same approach as above for port information 737 */ 738 create->tuple.flow_ident = ecm_db_connection_from_port_get(feci->ci); 739 create->tuple.return_ident = ecm_db_connection_to_port_get(feci->ci); 740 741 /* 742 * Destination Node(MAC) address. This address will be same for all to side intefaces 743 */ 744 ecm_db_connection_to_node_address_get(feci->ci, dest_mac); 745 memcpy(create->dest_mac, dest_mac, ETH_ALEN); 746 747 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first); 748 749 for (vif = 0; vif < valid_vif_idx ; vif++) { 750 DEBUG_TRACE("ACCEL UPDATE %p: UDP Accelerate connection %p\n" 751 "Rule flag: %x\n" 752 "Vif: %d\n" 753 "Protocol: %d\n" 754 "from_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n" 755 "to_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n" 756 "to_mtu: %u\n" 757 "to_mac: %pM\n" 758 "dest_iface_num: %u\n" 759 "out_vlan[0] %x\n" 760 "out_vlan[1] %x\n", 761 nmci, 762 feci->ci, 763 create->if_rule[vif].rule_flags, 764 vif, 765 create->tuple.protocol, 766 ECM_IP_ADDR_TO_OCTAL(create->tuple.flow_ip), create->tuple.flow_ident, 767 ECM_IP_ADDR_TO_OCTAL(create->tuple.return_ip), create->tuple.return_ident, 768 create->if_rule[vif].if_mtu, 769 create->if_rule[vif].if_mac, 770 create->if_rule[vif].if_num, 771 create->if_rule[vif].egress_vlan_tag[0], 772 create->if_rule[vif].egress_vlan_tag[1]); 773 774 } 775 776 /* 777 * Now that the rule has been constructed we re-compare the generation occurrance counter. 778 * If there has been a change then we abort because the rule may have been created using 779 * unstable data - especially if another thread has begun regeneration of the connection state. 780 * NOTE: This does not prevent a regen from being flagged immediately after this line of code either, 781 * or while the acceleration rule is in flight to the nss. 782 * This is only to check for consistency of rule state - not that the state is stale. 783 */ 784 if (regen_occurrances != ecm_db_connection_regeneration_occurrances_get(feci->ci)) { 785 DEBUG_INFO("%p: connection:%p regen occurred - aborting accel rule.\n", feci, feci->ci); 786 vfree(nim); 787 return -1; 788 } 789 790 /* 791 * Ref the connection before issuing an NSS rule 792 * This ensures that when the NSS responds to the command - which may even be immediately - 793 * the callback function can trust the correct ref was taken for its purpose. 794 * NOTE: remember that this will also implicitly hold the feci. 795 */ 796 ecm_db_connection_ref(feci->ci); 797 798 /* 799 * We are about to issue the command, record the time of transmission 800 */ 801 spin_lock_bh(&feci->lock); 802 feci->stats.cmd_time_begun = jiffies; 803 spin_unlock_bh(&feci->lock); 804 805 /* 806 * Call the rule create function 807 */ 808 nss_tx_status = nss_ipv6_tx(ecm_nss_ipv6_nss_ipv6_mgr, nim); 809 if (nss_tx_status == NSS_TX_SUCCESS) { 810 spin_lock_bh(&feci->lock); 811 nmci->base.stats.driver_fail = 0; /* Reset */ 812 spin_unlock_bh(&feci->lock); 813 vfree(nim); 814 return 0; 815 } 816 817 /* 818 * Revert accel mode if necessary 819 */ 820 DEBUG_WARN("%p: ACCEL UPDATE attempt failed\n", nmci); 821 822 /* 823 * Release that ref! 824 */ 825 ecm_db_connection_deref(feci->ci); 826 827 vfree(nim); 828 829 /* 830 * TX failed 831 */ 832 spin_lock_bh(&feci->lock); 833 feci->stats.driver_fail_total++; 834 feci->stats.driver_fail++; 835 if (nmci->base.stats.driver_fail >= nmci->base.stats.driver_fail_limit) { 836 DEBUG_WARN("%p: Accel failed - driver fail limit\n", nmci); 837 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER; 838 } 839 spin_unlock_bh(&feci->lock); 840 return -1; 841} 842 843/* 844 * ecm_nss_multicast_ipv6_connection_accelerate() 845 * Accelerate a multicast UDP connection 846 */ 847static void ecm_nss_multicast_ipv6_connection_accelerate(struct ecm_front_end_connection_instance *feci, 848 struct ecm_classifier_process_response *pr) 849{ 850 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 851 uint16_t regen_occurrances; 852 struct ecm_db_iface_instance *from_ifaces[ECM_DB_IFACE_HEIRARCHY_MAX]; 853 struct ecm_db_iface_instance *from_nss_iface; 854 int32_t from_ifaces_first; 855 struct ecm_db_iface_instance *to_ifaces; 856 struct ecm_db_iface_instance *ii_temp; 857 struct ecm_db_iface_instance *ii_single; 858 struct ecm_db_iface_instance **ifaces; 859 struct nss_ipv6_msg *nim; 860 ecm_db_iface_type_t from_iface_type = ECM_DB_IFACE_TYPE_COUNT; 861 ecm_db_iface_type_t to_iface_type = ECM_DB_IFACE_TYPE_COUNT; 862 int32_t *to_ifaces_first; 863 int32_t *to_ii_first; 864 int32_t from_nss_iface_id; 865 int32_t to_nss_iface_id; 866 uint8_t to_nss_iface_address[ETH_ALEN]; 867 ip_addr_t addr; 868 struct nss_ipv6_mc_rule_create_msg *create; 869 struct ecm_classifier_instance *assignments[ECM_CLASSIFIER_TYPES]; 870 int aci_index; 871 int32_t vif, ret; 872 int assignment_count; 873 int from_iface_identifier = 0; 874 int to_iface_bridge_identifier = 0; 875 nss_tx_status_t nss_tx_status; 876 int32_t list_index; 877 int32_t valid_vif_idx = 0; 878 int32_t interface_type_counts[ECM_DB_IFACE_TYPE_COUNT]; 879 uint8_t dest_mac[ETH_ALEN]; 880 bool rule_invalid; 881 ecm_front_end_acceleration_mode_t result_mode; 882 883 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 884 885 /* 886 * Get the re-generation occurrance counter of the connection. 887 * We compare it again at the end - to ensure that the rule construction has seen no generation 888 * changes during rule creation. 889 */ 890 regen_occurrances = ecm_db_connection_regeneration_occurrances_get(feci->ci); 891 892 /* 893 * Can this connection be accelerated at all? 894 */ 895 if (!ecm_nss_ipv6_accel_pending_set(feci)) { 896 DEBUG_TRACE("%p: Acceleration denied: %p\n", feci, feci->ci); 897 return; 898 } 899 900 /* 901 * Construct an accel command. 902 * Initialise Multicast create structure. 903 * NOTE: We leverage the app_data void pointer to be our 32 bit connection serial number. 904 * When we get it back we re-cast it to a uint32 and do a faster connection lookup. 905 */ 906 nim = (struct nss_ipv6_msg *)kzalloc(sizeof(struct nss_ipv6_msg), GFP_ATOMIC | __GFP_NOWARN); 907 if (!nim) { 908 return; 909 } 910 911 nss_ipv6_msg_init(nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_CREATE_MC_RULE_MSG, 912 sizeof(struct nss_ipv6_mc_rule_create_msg), 913 ecm_nss_multicast_ipv6_connection_create_callback, 914 (void *)ecm_db_connection_serial_get(feci->ci)); 915 916 create = &nim->msg.mc_rule_create; 917 918 /* 919 * Populate the multicast creation structure 920 */ 921 from_ifaces_first = ecm_db_connection_from_interfaces_get_and_ref(feci->ci, from_ifaces); 922 if (from_ifaces_first == ECM_DB_IFACE_HEIRARCHY_MAX) { 923 DEBUG_WARN("%p: Accel attempt failed - no interfaces in from_interfaces list!\n", nmci); 924 kfree(nim); 925 return; 926 } 927 928 create->ingress_vlan_tag[0] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED; 929 create->ingress_vlan_tag[1] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED; 930 from_nss_iface = from_ifaces[from_ifaces_first]; 931 from_nss_iface_id = ecm_db_iface_ae_interface_identifier_get(from_nss_iface); 932 933 if (from_nss_iface_id < 0) { 934 DEBUG_TRACE("%p: from_nss_iface_id: %d\n", nmci, from_nss_iface_id); 935 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first); 936 kfree(nim); 937 return; 938 } 939 940 memset(interface_type_counts, 0, sizeof(interface_type_counts)); 941 rule_invalid = false; 942 for (list_index = from_ifaces_first; list_index < ECM_DB_IFACE_HEIRARCHY_MAX; list_index++) { 943 struct ecm_db_iface_instance *ii; 944 ecm_db_iface_type_t ii_type; 945 char *ii_name; 946 947 ii = from_ifaces[list_index]; 948 ii_type = ecm_db_connection_iface_type_get(ii); 949 ii_name = ecm_db_interface_type_to_string(ii_type); 950 DEBUG_TRACE("%p: list_index: %d, ii: %p, type: %d (%s)\n", nmci, list_index, ii, ii_type, ii_name); 951 952 /* 953 * Extract information from this interface type if it is applicable to the rule. 954 * Conflicting information may cause accel to be unsupported. 955 */ 956 switch (ii_type) { 957#ifdef ECM_INTERFACE_VLAN_ENABLE 958 struct ecm_db_interface_info_vlan vlan_info; 959#endif 960 case ECM_DB_IFACE_TYPE_BRIDGE: 961 DEBUG_TRACE("%p: Bridge\n", nmci); 962 from_iface_type = ECM_DB_IFACE_TYPE_BRIDGE; 963 from_iface_identifier = ecm_db_iface_interface_identifier_get(ii); 964 break; 965 case ECM_DB_IFACE_TYPE_VLAN: 966#ifdef ECM_INTERFACE_VLAN_ENABLE 967 DEBUG_TRACE("%p: VLAN\n", nmci); 968 if (interface_type_counts[ii_type] > 1) { 969 970 /* 971 * Can only support two vlans 972 */ 973 rule_invalid = true; 974 DEBUG_TRACE("%p: VLAN - additional unsupported\n", nmci); 975 break; 976 } 977 ecm_db_iface_vlan_info_get(ii, &vlan_info); 978 create->ingress_vlan_tag[interface_type_counts[ii_type]] = ((vlan_info.vlan_tpid << 16) | vlan_info.vlan_tag); 979 create->valid_flags |= NSS_IPV6_MC_RULE_CREATE_FLAG_INGRESS_VLAN_VALID; 980 DEBUG_TRACE("%p: vlan tag: %x\n", nmci, create->ingress_vlan_tag[interface_type_counts[ii_type]]); 981#else 982 rule_invalid = true; 983 DEBUG_TRACE("%p: VLAN - unsupported\n", nmci); 984#endif 985 break; 986 default: 987 DEBUG_TRACE("%p: Ignoring: %d (%s)\n", nmci, ii_type, ii_name); 988 } 989 interface_type_counts[ii_type]++; 990 } 991 992 ecm_db_connection_interfaces_deref(from_ifaces, from_ifaces_first); 993 994 ret = ecm_db_multicast_connection_to_interfaces_get_and_ref_all(feci->ci, &to_ifaces, &to_ifaces_first); 995 if (!ret) { 996 DEBUG_WARN("%p: Accel attempt failed - no multicast interfaces in to_interfaces list!\n", nmci); 997 kfree(nim); 998 return; 999 } 1000 1001 1002 /* 1003 * Now examine the TO / DEST heirarchy list to construct the destination part of the rule 1004 */ 1005 DEBUG_TRACE("%p: Examine to/dest heirarchy list\n", nmci); 1006 rule_invalid = false; 1007 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 1008 int32_t to_mtu = 0; 1009 to_nss_iface_id = -1; 1010 to_iface_type = ECM_DB_IFACE_TYPE_COUNT; 1011 1012#ifdef ECM_INTERFACE_VLAN_ENABLE 1013 create->if_rule[vif].egress_vlan_tag[0] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED; 1014 create->if_rule[vif].egress_vlan_tag[1] = ECM_NSS_CONNMGR_VLAN_ID_NOT_CONFIGURED; 1015#endif 1016 1017 ii_temp = ecm_db_multicast_if_heirarchy_get(to_ifaces, vif); 1018 to_ii_first = ecm_db_multicast_if_first_get_at_index(to_ifaces_first, vif); 1019 memset(interface_type_counts, 0, sizeof(interface_type_counts)); 1020 1021 for (list_index = *to_ii_first; !rule_invalid && (list_index < ECM_DB_IFACE_HEIRARCHY_MAX); list_index++) { 1022 struct ecm_db_iface_instance *ii; 1023 ecm_db_iface_type_t ii_type; 1024 char *ii_name; 1025 1026 ii_single = ecm_db_multicast_if_instance_get_at_index(ii_temp, list_index); 1027 ifaces = (struct ecm_db_iface_instance **)ii_single; 1028 ii = *ifaces; 1029 ii_type = ecm_db_connection_iface_type_get(ii); 1030 ii_name = ecm_db_interface_type_to_string(ii_type); 1031 1032 DEBUG_TRACE("%p: list_index: %d, ii: %p, type: %d (%s)\n", nmci, list_index, ii, ii_type, ii_name); 1033 1034 /* 1035 * Extract information from this interface type if it is applicable to the rule. 1036 * Conflicting information may cause accel to be unsupported. 1037 */ 1038 switch (ii_type) { 1039#ifdef ECM_INTERFACE_PPP_ENABLE 1040 struct ecm_db_interface_info_pppoe pppoe_info; 1041#endif 1042#ifdef ECM_INTERFACE_VLAN_ENABLE 1043 struct ecm_db_interface_info_vlan vlan_info; 1044 struct net_device *vlan_out_dev = NULL; 1045 uint32_t vlan_prio = 0; 1046#endif 1047 case ECM_DB_IFACE_TYPE_BRIDGE: 1048 1049 /* 1050 * TODO: Find and set the bridge/route flag for this interface 1051 */ 1052 DEBUG_TRACE("%p: Bridge\n", nmci); 1053 if (interface_type_counts[ii_type] != 0) { 1054 1055 /* 1056 * Cannot cascade bridges 1057 */ 1058 rule_invalid = true; 1059 DEBUG_TRACE("%p: Bridge - ignore additional\n", nmci); 1060 break; 1061 } 1062 ecm_db_iface_bridge_address_get(ii, to_nss_iface_address); 1063 to_iface_type = ECM_DB_IFACE_TYPE_BRIDGE; 1064 to_iface_bridge_identifier = ecm_db_iface_interface_identifier_get(ii); 1065 DEBUG_TRACE("%p: Bridge - mac: %pM\n", nmci, to_nss_iface_address); 1066 break; 1067 case ECM_DB_IFACE_TYPE_ETHERNET: 1068 DEBUG_TRACE("%p: Ethernet\n", nmci); 1069 if (interface_type_counts[ii_type] != 0) { 1070 1071 /* 1072 * Ignore additional mac addresses, these are usually as a result of address propagation 1073 * from bridges down to ports etc. 1074 */ 1075 DEBUG_TRACE("%p: Ethernet - ignore additional\n", nmci); 1076 break; 1077 } 1078 1079 /* 1080 * Can only handle one MAC, the first outermost mac. 1081 */ 1082 ecm_db_iface_ethernet_address_get(ii, to_nss_iface_address); 1083 to_mtu = (uint32_t)ecm_db_connection_to_iface_mtu_get(feci->ci); 1084 to_nss_iface_id = ecm_db_iface_ae_interface_identifier_get(ii); 1085 if (to_nss_iface_id < 0) { 1086 DEBUG_TRACE("%p: to_nss_iface_id: %d\n", nmci, to_nss_iface_id); 1087 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first); 1088 kfree(nim); 1089 return; 1090 } 1091 1092 DEBUG_TRACE("%p: Ethernet - mac: %pM\n", nmci, to_nss_iface_address); 1093 break; 1094 case ECM_DB_IFACE_TYPE_PPPOE: 1095#ifdef ECM_INTERFACE_PPP_ENABLE 1096 /* 1097 * More than one PPPoE in the list is not valid! 1098 */ 1099 if (interface_type_counts[ii_type] != 0) { 1100 DEBUG_TRACE("%p: PPPoE - additional unsupported\n", nmci); 1101 rule_invalid = true; 1102 break; 1103 } 1104 1105 /* 1106 * Copy pppoe session info to the creation structure. 1107 */ 1108 ecm_db_iface_pppoe_session_info_get(ii, &pppoe_info); 1109 create->if_rule[valid_vif_idx].pppoe_session_id = pppoe_info.pppoe_session_id; 1110 memcpy(create->if_rule[valid_vif_idx].pppoe_remote_mac, pppoe_info.remote_mac, ETH_ALEN); 1111 create->if_rule[valid_vif_idx].valid_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_PPPOE_VALID; 1112 DEBUG_TRACE("%p: PPPoE - session: %x, mac: %pM\n", nmci, create->if_rule[valid_vif_idx].pppoe_session_id, create->if_rule[valid_vif_idx].pppoe_remote_mac); 1113#else 1114 DEBUG_TRACE("%p: PPPoE - unsupported\n", nmci); 1115 rule_invalid = true; 1116#endif 1117 break; 1118 case ECM_DB_IFACE_TYPE_VLAN: 1119#ifdef ECM_INTERFACE_VLAN_ENABLE 1120 DEBUG_TRACE("%p: VLAN\n", nmci); 1121 if (interface_type_counts[ii_type] > 1) { 1122 /* 1123 * Can only support two vlans 1124 */ 1125 rule_invalid = true; 1126 DEBUG_TRACE("%p: VLAN - additional unsupported\n", nmci); 1127 break; 1128 } 1129 1130 ecm_db_iface_vlan_info_get(ii, &vlan_info); 1131 create->if_rule[valid_vif_idx].egress_vlan_tag[interface_type_counts[ii_type]] = ((vlan_info.vlan_tpid << 16) | vlan_info.vlan_tag); 1132 1133 vlan_out_dev = dev_get_by_index(&init_net, ecm_db_iface_interface_identifier_get(ii)); 1134 if (vlan_out_dev) { 1135 vlan_prio = vlan_dev_get_egress_prio(vlan_out_dev, pr->flow_qos_tag); 1136 create->if_rule[valid_vif_idx].egress_vlan_tag[interface_type_counts[ii_type]] |= vlan_prio; 1137 dev_put(vlan_out_dev); 1138 vlan_out_dev = NULL; 1139 } 1140 1141 /* 1142 * If we have not yet got an ethernet mac then take this one (very unlikely as mac should have been propagated to the slave (outer) device 1143 */ 1144 if (interface_type_counts[ECM_DB_IFACE_TYPE_ETHERNET] == 0) { 1145 memcpy(to_nss_iface_address, vlan_info.address, ETH_ALEN); 1146 interface_type_counts[ECM_DB_IFACE_TYPE_ETHERNET]++; 1147 DEBUG_TRACE("%p: VLAN use mac: %pM\n", nmci, to_nss_iface_address); 1148 } 1149 create->if_rule[valid_vif_idx].valid_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_VLAN_VALID; 1150 DEBUG_TRACE("%p: vlan tag: %x\n", nmci, create->if_rule[vif].egress_vlan_tag[interface_type_counts[ii_type]]); 1151#else 1152 rule_invalid = true; 1153 DEBUG_TRACE("%p: VLAN - unsupported\n", nmci); 1154#endif 1155 break; 1156 default: 1157 DEBUG_TRACE("%p: Ignoring: %d (%s)\n", nmci, ii_type, ii_name); 1158 } 1159 1160 /* 1161 * Seen an interface of this type 1162 */ 1163 interface_type_counts[ii_type]++; 1164 } 1165 1166 if (rule_invalid) { 1167 DEBUG_WARN("%p: to/dest Rule invalid\n", nmci); 1168 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first); 1169 kfree(nim); 1170 return; 1171 } 1172 1173 /* 1174 * Populate the interface details for a valid interface in the multicast destination 1175 * interface list. 1176 */ 1177 if (to_nss_iface_id != -1) { 1178 bool is_bridge; 1179 create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_JOIN; 1180 create->if_rule[valid_vif_idx].if_num = to_nss_iface_id; 1181 create->if_rule[valid_vif_idx].if_mtu = to_mtu; 1182 1183 is_bridge = !ecm_db_connection_is_routed_get(feci->ci); 1184 1185 /* 1186 * Identify if the destination interface blongs to pure bridge or routed flow. 1187 */ 1188 if (((from_iface_type == ECM_DB_IFACE_TYPE_BRIDGE && 1189 to_iface_type == ECM_DB_IFACE_TYPE_BRIDGE) || is_bridge) && 1190 (from_iface_identifier == to_iface_bridge_identifier)) { 1191 uint8_t from_nss_iface_address[ETH_ALEN]; 1192 ecm_db_connection_from_node_address_get(feci->ci, (uint8_t *)from_nss_iface_address); 1193 memcpy(create->if_rule[valid_vif_idx].if_mac, from_nss_iface_address, ETH_ALEN); 1194 create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_BRIDGE_FLOW; 1195 } else { 1196 memcpy(create->if_rule[valid_vif_idx].if_mac, to_nss_iface_address, ETH_ALEN); 1197 create->if_rule[valid_vif_idx].rule_flags |= NSS_IPV6_MC_RULE_CREATE_IF_FLAG_ROUTED_FLOW; 1198 } 1199 1200 valid_vif_idx++; 1201 } 1202 } 1203 1204 create->if_count = valid_vif_idx; 1205 create->src_interface_num = from_nss_iface_id; 1206 1207 /* 1208 * Set up the flow qos tags 1209 */ 1210 create->qos_tag = (uint32_t)pr->flow_qos_tag; 1211 1212 /* 1213 * DSCP information? 1214 */ 1215 if (pr->process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DSCP) { 1216 create->egress_dscp = pr->flow_dscp; 1217 create->valid_flags |= NSS_IPV6_MC_RULE_CREATE_FLAG_DSCP_MARKING_VALID; 1218 } 1219 1220 ecm_db_connection_to_node_address_get(feci->ci, dest_mac); 1221 memcpy(create->dest_mac, dest_mac, ETH_ALEN); 1222 1223 /* 1224 * Set protocol 1225 */ 1226 create->tuple.protocol = IPPROTO_UDP; 1227 1228 /* 1229 * The src_ip is where the connection established from 1230 */ 1231 ecm_db_connection_from_address_get(feci->ci, addr); 1232 ECM_IP_ADDR_TO_NSS_IPV6_ADDR(create->tuple.flow_ip, addr); 1233 1234 1235 /* 1236 * The destination address is what the destination IP is translated to as it is forwarded to the next interface. 1237 * For egress this would yield the normal wan host and for ingress this would correctly NAT back to the LAN host 1238 */ 1239 ecm_db_connection_to_address_get(feci->ci, addr); 1240 ECM_IP_ADDR_TO_NSS_IPV6_ADDR(create->tuple.return_ip, addr); 1241 1242 /* 1243 * Same approach as above for port information 1244 */ 1245 create->tuple.flow_ident = ecm_db_connection_from_port_get(feci->ci); 1246 create->tuple.return_ident = ecm_db_connection_to_port_get(feci->ci); 1247 1248 /* 1249 * Sync our creation command from the assigned classifiers to get specific additional creation rules. 1250 * NOTE: These are called in ascending order of priority and so the last classifier (highest) shall 1251 * override any preceding classifiers. 1252 * This also gives the classifiers a chance to see that acceleration is being attempted. 1253 */ 1254 assignment_count = ecm_db_connection_classifier_assignments_get_and_ref(feci->ci, assignments); 1255 for (aci_index = 0; aci_index < assignment_count; ++aci_index) { 1256 struct ecm_classifier_instance *aci; 1257 struct ecm_classifier_rule_create ecrc; 1258 /* 1259 * NOTE: The current classifiers do not sync anything to the underlying accel engines. 1260 * In the future, if any of the classifiers wants to pass any parameter, these parameters 1261 * should be received via this object and copied to the accel engine's create object (nircm). 1262 */ 1263 aci = assignments[aci_index]; 1264 DEBUG_TRACE("%p: sync from: %p, type: %d\n", nmci, aci, aci->type_get(aci)); 1265 aci->sync_from_v6(aci, &ecrc); 1266 } 1267 ecm_db_connection_assignments_release(assignment_count, assignments); 1268 1269 /* 1270 * Release the interface lists 1271 */ 1272 ecm_db_multicast_connection_to_interfaces_deref_all(to_ifaces, to_ifaces_first); 1273 1274 for (vif = 0; vif < valid_vif_idx ; vif++){ 1275 DEBUG_TRACE("%p: UDP Accelerate connection %p\n" 1276 "Vif: %d\n" 1277 "Protocol: %d\n" 1278 "to_mtu: %u\n" 1279 "from_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n" 1280 "to_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n" 1281 "to_mac: %pM\n" 1282 "dest_iface_num: %u\n" 1283 "in_vlan[0] %x\n" 1284 "in_vlan[1] %x\n" 1285 "out_vlan[0] %x\n" 1286 "out_vlan[1] %x\n", 1287 nmci, 1288 feci->ci, 1289 vif, 1290 create->tuple.protocol, 1291 create->if_rule[vif].if_mtu, 1292 ECM_IP_ADDR_TO_OCTAL(create->tuple.flow_ip), create->tuple.flow_ident, 1293 ECM_IP_ADDR_TO_OCTAL(create->tuple.return_ip), create->tuple.return_ident, 1294 create->if_rule[vif].if_mac, 1295 create->if_rule[vif].if_num, 1296 create->ingress_vlan_tag[0], 1297 create->ingress_vlan_tag[1], 1298 create->if_rule[vif].egress_vlan_tag[0], 1299 create->if_rule[vif].egress_vlan_tag[1]); 1300 } 1301 1302 /* 1303 * Now that the rule has been constructed we re-compare the generation occurrance counter. 1304 * If there has been a change then we abort because the rule may have been created using 1305 * unstable data - especially if another thread has begun regeneration of the connection state. 1306 * NOTE: This does not prevent a regen from being flagged immediately after this line of code either, 1307 * or while the acceleration rule is in flight to the nss. 1308 * This is only to check for consistency of rule state - not that the state is stale. 1309 * Remember that the connection is marked as "accel pending state" so if a regen is flagged immediately 1310 * after this check passes, the connection will be decelerated and refreshed very quickly. 1311 */ 1312 if (regen_occurrances != ecm_db_connection_regeneration_occurrances_get(feci->ci)) { 1313 DEBUG_INFO("%p: connection:%p regen occurred - aborting accel rule.\n", feci, feci->ci); 1314 ecm_nss_ipv6_accel_pending_clear(feci, ECM_FRONT_END_ACCELERATION_MODE_DECEL); 1315 kfree(nim); 1316 return; 1317 } 1318 1319 /* 1320 * Ref the connection before issuing an NSS rule 1321 * This ensures that when the NSS responds to the command - which may even be immediately - 1322 * the callback function can trust the correct ref was taken for its purpose. 1323 * NOTE: remember that this will also implicitly hold the feci. 1324 */ 1325 ecm_db_connection_ref(feci->ci); 1326 1327 /* 1328 * We are about to issue the command, record the time of transmission 1329 */ 1330 spin_lock_bh(&feci->lock); 1331 feci->stats.cmd_time_begun = jiffies; 1332 spin_unlock_bh(&feci->lock); 1333 1334 /* 1335 * Call the rule create function 1336 */ 1337 nss_tx_status = nss_ipv6_tx(ecm_nss_ipv6_nss_ipv6_mgr, nim); 1338 if (nss_tx_status == NSS_TX_SUCCESS) { 1339 1340 /* 1341 * Reset the driver_fail count - transmission was okay here. 1342 */ 1343 spin_lock_bh(&feci->lock); 1344 nmci->base.stats.driver_fail = 0; /* Reset */ 1345 spin_unlock_bh(&feci->lock); 1346 kfree(nim); 1347 return; 1348 } 1349 1350 /* 1351 * Release that ref! 1352 */ 1353 ecm_db_connection_deref(feci->ci); 1354 1355 /* 1356 * TX failed 1357 */ 1358 spin_lock_bh(&feci->lock); 1359 DEBUG_ASSERT(feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING, "%p: accel mode unexpected: %d\n", nmci, feci->accel_mode); 1360 feci->stats.driver_fail_total++; 1361 feci->stats.driver_fail++; 1362 if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) { 1363 DEBUG_WARN("%p: Accel failed - driver fail limit\n", nmci); 1364 result_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER; 1365 } else { 1366 result_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL; 1367 } 1368 1369 spin_lock_bh(&ecm_nss_ipv6_lock); 1370 _ecm_nss_ipv6_accel_pending_clear(feci, result_mode); 1371 spin_unlock_bh(&ecm_nss_ipv6_lock); 1372 1373 spin_unlock_bh(&feci->lock); 1374 kfree(nim); 1375 return; 1376} 1377 1378/* 1379 * ecm_nss_multicast_ipv6_connection_destroy_callback() 1380 * Callback for handling destroy ack/nack calls. 1381 */ 1382static void ecm_nss_multicast_ipv6_connection_destroy_callback(void *app_data, struct nss_ipv6_msg *nim) 1383{ 1384 struct nss_ipv6_rule_destroy_msg *nirdm = &nim->msg.rule_destroy; 1385 uint32_t serial = (uint32_t)app_data; 1386 struct ecm_db_connection_instance *ci; 1387 struct ecm_front_end_connection_instance *feci; 1388 struct ecm_nss_multicast_ipv6_connection_instance *nmci; 1389 ip_addr_t flow_ip; 1390 ip_addr_t return_ip; 1391 1392 /* 1393 * Is this a response to a destroy message? 1394 */ 1395 if (nim->cm.type != NSS_IPV6_TX_DESTROY_RULE_MSG) { 1396 DEBUG_ERROR("%p: multicast destroy callback with improper type: %d\n", nim, nim->cm.type); 1397 return; 1398 } 1399 1400 /* 1401 * Look up ecm connection so that we can update the status. 1402 */ 1403 ci = ecm_db_connection_serial_find_and_ref(serial); 1404 if (!ci) { 1405 DEBUG_TRACE("%p: destroy callback, connection not found, serial: %u\n", nim, serial); 1406 return; 1407 } 1408 1409 /* 1410 * Release ref held for this ack/nack response. 1411 * NOTE: It's okay to do this here, ci won't go away, because the ci is held as 1412 * a result of the ecm_db_connection_serial_find_and_ref() 1413 */ 1414 ecm_db_connection_deref(ci); 1415 1416 /* 1417 * Get the front end instance 1418 */ 1419 feci = ecm_db_connection_front_end_get_and_ref(ci); 1420 nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 1421 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 1422 1423 ECM_NSS_IPV6_ADDR_TO_IP_ADDR(flow_ip, nirdm->tuple.flow_ip); 1424 ECM_NSS_IPV6_ADDR_TO_IP_ADDR(return_ip, nirdm->tuple.return_ip); 1425 1426 /* 1427 * Record command duration 1428 */ 1429 ecm_nss_ipv6_decel_done_time_update(feci); 1430 1431 /* 1432 * Dump some useful trace information. 1433 */ 1434 DEBUG_TRACE("%p: decelerate response for connection: %p\n", nmci, feci->ci); 1435 DEBUG_TRACE("%p: flow_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(flow_ip), nirdm->tuple.flow_ident); 1436 DEBUG_TRACE("%p: return_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", nmci, ECM_IP_ADDR_TO_OCTAL(return_ip), nirdm->tuple.return_ident); 1437 DEBUG_TRACE("%p: protocol: %d\n", nmci, nirdm->tuple.protocol); 1438 1439 /* 1440 * Drop decel pending counter 1441 */ 1442 spin_lock_bh(&ecm_nss_ipv6_lock); 1443 ecm_nss_ipv6_pending_decel_count--; 1444 DEBUG_ASSERT(ecm_nss_ipv6_pending_decel_count >= 0, "Bad decel pending counter\n"); 1445 spin_unlock_bh(&ecm_nss_ipv6_lock); 1446 1447 spin_lock_bh(&feci->lock); 1448 1449 /* 1450 * If decel is not still pending then it's possible that the NSS ended acceleration by some other reason e.g. flush 1451 * In which case we cannot rely on the response we get here. 1452 */ 1453 if (feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_DECEL_PENDING) { 1454 spin_unlock_bh(&feci->lock); 1455 1456 /* 1457 * Release the connections. 1458 */ 1459 feci->deref(feci); 1460 ecm_db_connection_deref(ci); 1461 return; 1462 } 1463 1464 DEBUG_TRACE("%p: response: %d\n", nmci, nim->cm.response); 1465 if (nim->cm.response != NSS_CMN_RESPONSE_ACK) { 1466 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DECEL; 1467 } else { 1468 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL; 1469 } 1470 1471 /* 1472 * If connection became defunct then set mode so that no further accel/decel attempts occur. 1473 */ 1474 if (feci->is_defunct) { 1475 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DEFUNCT; 1476 } 1477 1478 spin_unlock_bh(&feci->lock); 1479 1480 /* 1481 * Multicast acceleration ends 1482 */ 1483 spin_lock_bh(&ecm_nss_ipv6_lock); 1484 ecm_nss_multicast_ipv6_accelerated_count--; /* Protocol specific counter */ 1485 DEBUG_ASSERT(ecm_nss_multicast_ipv6_accelerated_count >= 0, "Bad udp accel counter\n"); 1486 ecm_nss_ipv6_accelerated_count--; /* General running counter */ 1487 DEBUG_ASSERT(ecm_nss_ipv6_accelerated_count >= 0, "Bad accel counter\n"); 1488 spin_unlock_bh(&ecm_nss_ipv6_lock); 1489 1490 /* 1491 * Release the connections. 1492 */ 1493 feci->deref(feci); 1494 ecm_db_connection_deref(ci); 1495} 1496 1497/* 1498 * ecm_nss_multicast_ipv6_connection_decelerate() 1499 * Decelerate a connection 1500 */ 1501static void ecm_nss_multicast_ipv6_connection_decelerate(struct ecm_front_end_connection_instance *feci) 1502{ 1503 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 1504 struct nss_ipv6_msg nim; 1505 struct nss_ipv6_rule_destroy_msg *nirdm; 1506 ip_addr_t src_ip; 1507 ip_addr_t dest_ip; 1508 nss_tx_status_t nss_tx_status; 1509 1510 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 1511 1512 /* 1513 * If decelerate is in error or already pending then ignore 1514 */ 1515 spin_lock_bh(&feci->lock); 1516 if (feci->stats.decelerate_pending) { 1517 spin_unlock_bh(&feci->lock); 1518 return; 1519 } 1520 1521 /* 1522 * If acceleration is pending then we cannot decelerate right now or we will race with it 1523 * Set a decelerate pending flag that will be actioned when the acceleration command is complete. 1524 */ 1525 if (feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING) { 1526 feci->stats.decelerate_pending = true; 1527 spin_unlock_bh(&feci->lock); 1528 return; 1529 } 1530 1531 /* 1532 * Can only decelerate if accelerated 1533 * NOTE: This will also deny accel when the connection is in fail condition too. 1534 */ 1535 if (feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_ACCEL) { 1536 spin_unlock_bh(&feci->lock); 1537 return; 1538 } 1539 1540 /* 1541 * Initiate deceleration 1542 */ 1543 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL_PENDING; 1544 spin_unlock_bh(&feci->lock); 1545 1546 /* 1547 * Increment the decel pending counter 1548 */ 1549 spin_lock_bh(&ecm_nss_ipv6_lock); 1550 ecm_nss_ipv6_pending_decel_count++; 1551 spin_unlock_bh(&ecm_nss_ipv6_lock); 1552 1553 /* 1554 * Prepare deceleration message 1555 */ 1556 nss_ipv6_msg_init(&nim, NSS_IPV6_RX_INTERFACE, NSS_IPV6_TX_DESTROY_RULE_MSG, 1557 sizeof(struct nss_ipv6_rule_destroy_msg), 1558 ecm_nss_multicast_ipv6_connection_destroy_callback, 1559 (void *)ecm_db_connection_serial_get(feci->ci)); 1560 1561 nirdm = &nim.msg.rule_destroy; 1562 nirdm->tuple.protocol = (int32_t)ecm_db_connection_protocol_get(feci->ci); 1563 1564 /* 1565 * Get addressing information 1566 */ 1567 ecm_db_connection_from_address_get(feci->ci, src_ip); 1568 ECM_IP_ADDR_TO_NSS_IPV6_ADDR(nirdm->tuple.flow_ip, src_ip); 1569 ecm_db_connection_to_address_get(feci->ci, dest_ip); 1570 ECM_IP_ADDR_TO_NSS_IPV6_ADDR(nirdm->tuple.return_ip, dest_ip); 1571 nirdm->tuple.flow_ident = ecm_db_connection_from_port_get(feci->ci); 1572 nirdm->tuple.return_ident = ecm_db_connection_to_port_get(feci->ci); 1573 1574 DEBUG_INFO("%p: Mcast Connection %p decelerate\n" 1575 "src_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n" 1576 "dest_ip: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", 1577 nmci, feci->ci, 1578 ECM_IP_ADDR_TO_OCTAL(src_ip), nirdm->tuple.flow_ident, 1579 ECM_IP_ADDR_TO_OCTAL(dest_ip), nirdm->tuple.return_ident); 1580 1581 1582 /* 1583 * Right place to free the multicast destination interfaces list. 1584 */ 1585 ecm_db_multicast_connection_to_interfaces_clear(feci->ci); 1586 1587 /* 1588 * Take a ref to the feci->ci so that it will persist until we get a response from the NSS. 1589 * NOTE: This will implicitly hold the feci too. 1590 */ 1591 ecm_db_connection_ref(feci->ci); 1592 1593 /* 1594 * We are about to issue the command, record the time of transmission 1595 */ 1596 spin_lock_bh(&feci->lock); 1597 feci->stats.cmd_time_begun = jiffies; 1598 spin_unlock_bh(&feci->lock); 1599 1600 /* 1601 * Destroy the NSS connection cache entry. 1602 */ 1603 nss_tx_status = nss_ipv6_tx(ecm_nss_ipv6_nss_ipv6_mgr, &nim); 1604 if (nss_tx_status == NSS_TX_SUCCESS) { 1605 /* 1606 * Reset the driver_fail count - transmission was okay here. 1607 */ 1608 spin_lock_bh(&feci->lock); 1609 feci->stats.driver_fail = 0; 1610 spin_unlock_bh(&feci->lock); 1611 return; 1612 } 1613 1614 /* 1615 * Release the ref take, NSS driver did not accept our command. 1616 */ 1617 ecm_db_connection_deref(feci->ci); 1618 1619 /* 1620 * TX failed 1621 */ 1622 spin_lock_bh(&feci->lock); 1623 feci->stats.driver_fail_total++; 1624 feci->stats.driver_fail++; 1625 if (feci->stats.driver_fail >= feci->stats.driver_fail_limit) { 1626 DEBUG_WARN("%p: Decel failed - driver fail limit\n", nmci); 1627 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DRIVER; 1628 } 1629 spin_unlock_bh(&feci->lock); 1630 1631 /* 1632 * Could not send the request, decrement the decel pending counter 1633 */ 1634 spin_lock_bh(&ecm_nss_ipv6_lock); 1635 ecm_nss_ipv6_pending_decel_count--; 1636 DEBUG_ASSERT(ecm_nss_ipv6_pending_decel_count >= 0, "Bad decel pending counter\n"); 1637 spin_unlock_bh(&ecm_nss_ipv6_lock); 1638 1639} 1640 1641/* 1642 * ecm_nss_multicast_ipv6_connection_defunct_callback() 1643 * Callback to be called when a Mcast connection has become defunct. 1644 */ 1645static void ecm_nss_multicast_ipv6_connection_defunct_callback(void *arg) 1646{ 1647 struct ecm_front_end_connection_instance *feci = (struct ecm_front_end_connection_instance *)arg; 1648 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 1649 1650 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 1651 1652 spin_lock_bh(&feci->lock); 1653 1654 /* 1655 * If connection has already become defunct, do nothing. 1656 */ 1657 if (feci->is_defunct) { 1658 spin_unlock_bh(&feci->lock); 1659 return; 1660 } 1661 feci->is_defunct = true; 1662 1663 /* 1664 * If the connection is already in one of the fail modes, do nothing, keep the current accel_mode. 1665 */ 1666 if (ECM_FRONT_END_ACCELERATION_FAILED(feci->accel_mode)) { 1667 spin_unlock_bh(&feci->lock); 1668 return; 1669 } 1670 1671 /* 1672 * If the connection is decel then ensure it will not attempt accel while defunct. 1673 */ 1674 if (feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_DECEL) { 1675 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_DEFUNCT; 1676 spin_unlock_bh(&feci->lock); 1677 return; 1678 } 1679 1680 /* 1681 * If the connection is decel pending then decel operation is in progress anyway. 1682 */ 1683 if (feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_DECEL_PENDING) { 1684 spin_unlock_bh(&feci->lock); 1685 return; 1686 } 1687 1688 /* 1689 * If none of the cases matched above, this means the connection is in one of the 1690 * accel modes (accel or accel_pending) so we force a deceleration. 1691 * NOTE: If the mode is accel pending then the decel will be actioned when that is completed. 1692 */ 1693 spin_unlock_bh(&feci->lock); 1694 ecm_nss_multicast_ipv6_connection_decelerate(feci); 1695} 1696 1697/* 1698 * ecm_nss_multicast_ipv6_connection_accel_state_get() 1699 * Get acceleration state 1700 */ 1701static ecm_front_end_acceleration_mode_t ecm_nss_multicast_ipv6_connection_accel_state_get(struct ecm_front_end_connection_instance *feci) 1702{ 1703 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 1704 ecm_front_end_acceleration_mode_t state; 1705 1706 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 1707 spin_lock_bh(&feci->lock); 1708 state = feci->accel_mode; 1709 spin_unlock_bh(&feci->lock); 1710 return state; 1711} 1712 1713/* 1714 * ecm_nss_multicast_ipv6_connection_action_seen() 1715 * Acceleration action / activity has been seen for this connection. 1716 * 1717 * NOTE: Call the action_seen() method when the NSS has demonstrated that it has offloaded some data for a connection. 1718 */ 1719static void ecm_nss_multicast_ipv6_connection_action_seen(struct ecm_front_end_connection_instance *feci) 1720{ 1721 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 1722 1723 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 1724 DEBUG_INFO("%p: Action seen\n", nmci); 1725 spin_lock_bh(&feci->lock); 1726 feci->stats.no_action_seen = 0; 1727 spin_unlock_bh(&feci->lock); 1728} 1729 1730/* 1731 * ecm_nss_multicast_ipv6_connection_accel_ceased() 1732 * NSS has indicated that acceleration has stopped. 1733 * 1734 * NOTE: This is called in response to an NSS self-initiated termination of acceleration. 1735 * This must NOT be called because the ECM terminated the acceleration. 1736 */ 1737static void ecm_nss_multicast_ipv6_connection_accel_ceased(struct ecm_front_end_connection_instance *feci) 1738{ 1739 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 1740 1741 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 1742 DEBUG_INFO("%p: accel ceased\n", nmci); 1743 1744 spin_lock_bh(&feci->lock); 1745 1746 /* 1747 * If we are in accel-pending state then the NSS has issued a flush out-of-order 1748 * with the ACK/NACK we are actually waiting for. 1749 * To work around this we record a "flush has already happened" and will action it when we finally get that ACK/NACK. 1750 * GGG TODO This should eventually be removed when the NSS honours messaging sequence. 1751 */ 1752 if (feci->accel_mode == ECM_FRONT_END_ACCELERATION_MODE_ACCEL_PENDING) { 1753 feci->stats.flush_happened = true; 1754 feci->stats.flush_happened_total++; 1755 spin_unlock_bh(&feci->lock); 1756 return; 1757 } 1758 1759 /* 1760 * If connection is no longer accelerated by the time we get here just ignore the command 1761 */ 1762 if (feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_ACCEL) { 1763 spin_unlock_bh(&feci->lock); 1764 return; 1765 } 1766 1767 /* 1768 * If the no_action_seen counter was not reset then acceleration ended without any offload action 1769 */ 1770 if (feci->stats.no_action_seen) { 1771 feci->stats.no_action_seen_total++; 1772 } 1773 1774 /* 1775 * If the no_action_seen indicates successive cessations of acceleration without any offload action occuring 1776 * then we fail out this connection 1777 */ 1778 if (feci->stats.no_action_seen >= feci->stats.no_action_seen_limit) { 1779 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_FAIL_NO_ACTION; 1780 } else { 1781 feci->accel_mode = ECM_FRONT_END_ACCELERATION_MODE_DECEL; 1782 } 1783 spin_unlock_bh(&feci->lock); 1784 1785 /* 1786 * Mcast acceleration ends 1787 */ 1788 spin_lock_bh(&ecm_nss_ipv6_lock); 1789 ecm_nss_multicast_ipv6_accelerated_count--; /* Protocol specific counter */ 1790 DEBUG_ASSERT(ecm_nss_multicast_ipv6_accelerated_count >= 0, "Bad Mcast accel counter\n"); 1791 ecm_nss_ipv6_accelerated_count--; /* General running counter */ 1792 DEBUG_ASSERT(ecm_nss_ipv6_accelerated_count >= 0, "Bad accel counter\n"); 1793 spin_unlock_bh(&ecm_nss_ipv6_lock); 1794} 1795 1796/* 1797 * ecm_nss_multicast_ipv6_connection_ref() 1798 * Ref a connection front end instance 1799 */ 1800static void ecm_nss_multicast_ipv6_connection_ref(struct ecm_front_end_connection_instance *feci) 1801{ 1802 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 1803 1804 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 1805 spin_lock_bh(&feci->lock); 1806 feci->refs++; 1807 DEBUG_TRACE("%p: nmci ref %d\n", nmci, feci->refs); 1808 DEBUG_ASSERT(feci->refs > 0, "%p: ref wrap\n", nmci); 1809 spin_unlock_bh(&feci->lock); 1810} 1811 1812/* 1813 * ecm_nss_multicast_ipv6_connection_deref() 1814 * Deref a connection front end instance 1815 */ 1816static int ecm_nss_multicast_ipv6_connection_deref(struct ecm_front_end_connection_instance *feci) 1817{ 1818 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 1819 1820 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 1821 1822 spin_lock_bh(&feci->lock); 1823 feci->refs--; 1824 DEBUG_ASSERT(feci->refs >= 0, "%p: ref wrap\n", nmci); 1825 1826 if (feci->refs > 0) { 1827 int refs = feci->refs; 1828 spin_unlock_bh(&feci->lock); 1829 DEBUG_TRACE("%p: nmci deref %d\n", nmci, refs); 1830 return refs; 1831 } 1832 spin_unlock_bh(&feci->lock); 1833 1834 /* 1835 * We can now destroy the instance 1836 */ 1837 DEBUG_TRACE("%p: nmci final\n", nmci); 1838 DEBUG_CLEAR_MAGIC(nmci); 1839 kfree(nmci); 1840 1841 return 0; 1842} 1843 1844/* 1845 * ecm_nss_multicast_ipv6_connection_regenerate() 1846 * Re-generate a connection. 1847 * 1848 * Re-generating a connection involves re-evaluating the interface lists in case interface heirarchies have changed. 1849 * It also involves the possible triggering of classifier re-evaluation but only if all currently assigned 1850 * classifiers permit this operation. 1851 */ 1852static void ecm_nss_multicast_ipv6_connection_regenerate(struct ecm_db_connection_instance *ci, ecm_tracker_sender_type_t sender, 1853 struct net_device *out_dev, struct net_device *in_dev) 1854{ 1855 int i; 1856 bool reclassify_allowed; 1857 struct ecm_db_iface_instance *from_list[ECM_DB_IFACE_HEIRARCHY_MAX]; 1858 int32_t from_list_first; 1859 ip_addr_t ip_src_addr; 1860 ip_addr_t ip_dest_addr; 1861 int protocol; 1862 bool is_routed; 1863 uint8_t src_node_addr[ETH_ALEN]; 1864 uint8_t dest_node_addr[ETH_ALEN]; 1865 int assignment_count; 1866 struct ecm_classifier_instance *assignments[ECM_CLASSIFIER_TYPES]; 1867 struct ecm_front_end_connection_instance *feci; 1868 1869 /* 1870 * Update the interface lists - these may have changed, e.g. LAG path change etc. 1871 * NOTE: We never have to change the usual mapping->host->node_iface arrangements for each side of the connection (to/from sides) 1872 * This is because if these interfaces change then the connection is dead anyway. 1873 * But a LAG slave might change the heirarchy the connection is using but the LAG master is still sane. 1874 * If any of the new interface heirarchies cannot be created then simply set empty-lists as this will deny 1875 * acceleration and ensure that a bad rule cannot be created. 1876 * IMPORTANT: The 'sender' defines who has sent the packet that triggered this re-generation 1877 */ 1878 protocol = ecm_db_connection_protocol_get(ci); 1879 is_routed = ecm_db_connection_is_routed_get(ci); 1880 1881 ecm_db_connection_from_address_get(ci, ip_src_addr); 1882 ecm_db_connection_to_address_get(ci, ip_dest_addr); 1883 ecm_db_connection_from_node_address_get(ci, src_node_addr); 1884 ecm_db_connection_to_node_address_get(ci, dest_node_addr); 1885 1886 feci = ecm_db_connection_front_end_get_and_ref(ci); 1887 1888 DEBUG_TRACE("%p: Update the 'from' interface heirarchy list\n", ci); 1889 from_list_first = ecm_interface_heirarchy_construct(feci, from_list, ip_dest_addr, ip_src_addr, 4, protocol, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr, NULL); 1890 if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) { 1891 goto ecm_multicast_ipv6_retry_regen; 1892 } 1893 1894 ecm_db_connection_from_interfaces_reset(ci, from_list, from_list_first); 1895 ecm_db_connection_interfaces_deref(from_list, from_list_first); 1896 1897 feci->deref(feci); 1898 1899 /* 1900 * Get list of assigned classifiers to reclassify. 1901 * Remember: This also includes our default classifier too. 1902 */ 1903 assignment_count = ecm_db_connection_classifier_assignments_get_and_ref(ci, assignments); 1904 1905 /* 1906 * All of the assigned classifiers must permit reclassification. 1907 */ 1908 reclassify_allowed = true; 1909 for (i = 0; i < assignment_count; ++i) { 1910 DEBUG_TRACE("%p: Calling to reclassify: %p, type: %d\n", ci, assignments[i], assignments[i]->type_get(assignments[i])); 1911 if (!assignments[i]->reclassify_allowed(assignments[i])) { 1912 DEBUG_TRACE("%p: reclassify denied: %p, by type: %d\n", ci, assignments[i], assignments[i]->type_get(assignments[i])); 1913 reclassify_allowed = false; 1914 break; 1915 } 1916 } 1917 1918 /* 1919 * Re-generation of state is successful. 1920 */ 1921 ecm_db_conection_regeneration_completed(ci); 1922 1923 /* 1924 * Now we action any classifier re-classify 1925 */ 1926 if (!reclassify_allowed) { 1927 /* 1928 * Regeneration came to a successful conclusion even though reclassification was denied 1929 */ 1930 DEBUG_WARN("%p: re-classify denied\n", ci); 1931 1932 /* 1933 * Release the assignments 1934 */ 1935 ecm_db_connection_assignments_release(assignment_count, assignments); 1936 return; 1937 } 1938 1939 /* 1940 * Reclassify 1941 */ 1942 DEBUG_INFO("%p: reclassify\n", ci); 1943 if (!ecm_nss_ipv6_reclassify(ci, assignment_count, assignments)) { 1944 /* 1945 * We could not set up the classifiers to reclassify, it is safer to fail out and try again next time 1946 */ 1947 DEBUG_WARN("%p: Regeneration: reclassify failed\n", ci); 1948 ecm_db_connection_assignments_release(assignment_count, assignments); 1949 return; 1950 } 1951 DEBUG_INFO("%p: reclassify success\n", ci); 1952 1953 /* 1954 * Release the assignments 1955 */ 1956 ecm_db_connection_assignments_release(assignment_count, assignments); 1957 return; 1958 1959ecm_multicast_ipv6_retry_regen: 1960 feci->deref(feci); 1961 ecm_db_conection_regeneration_failed(ci); 1962 return; 1963} 1964 1965#ifdef ECM_STATE_OUTPUT_ENABLE 1966/* 1967 * ecm_nss_multicast_ipv6_connection_state_get() 1968 * Return state of this multicast front end instance 1969 */ 1970static int ecm_nss_multicast_ipv6_connection_state_get(struct ecm_front_end_connection_instance *feci, struct ecm_state_file_instance *sfi) 1971{ 1972 int result; 1973 bool can_accel; 1974 ecm_front_end_acceleration_mode_t accel_mode; 1975 struct ecm_front_end_connection_mode_stats stats; 1976 struct ecm_nss_multicast_ipv6_connection_instance *nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)feci; 1977 1978 DEBUG_CHECK_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC, "%p: magic failed", nmci); 1979 1980 spin_lock_bh(&feci->lock); 1981 can_accel = feci->can_accel; 1982 accel_mode = feci->accel_mode; 1983 memcpy(&stats, &feci->stats, sizeof(struct ecm_front_end_connection_mode_stats)); 1984 spin_unlock_bh(&feci->lock); 1985 1986 if ((result = ecm_state_prefix_add(sfi, "front_end_v6.multicast"))) { 1987 return result; 1988 } 1989 1990 if ((result = ecm_state_write(sfi, "can_accel", "%d", can_accel))) { 1991 return result; 1992 } 1993 if ((result = ecm_state_write(sfi, "accel_mode", "%d", accel_mode))) { 1994 return result; 1995 } 1996 if ((result = ecm_state_write(sfi, "decelerate_pending", "%d", stats.decelerate_pending))) { 1997 return result; 1998 } 1999 if ((result = ecm_state_write(sfi, "flush_happened_total", "%d", stats.flush_happened_total))) { 2000 return result; 2001 } 2002 if ((result = ecm_state_write(sfi, "no_action_seen_total", "%d", stats.no_action_seen_total))) { 2003 return result; 2004 } 2005 if ((result = ecm_state_write(sfi, "no_action_seen", "%d", stats.no_action_seen))) { 2006 return result; 2007 } 2008 if ((result = ecm_state_write(sfi, "no_action_seen_limit", "%d", stats.no_action_seen_limit))) { 2009 return result; 2010 } 2011 if ((result = ecm_state_write(sfi, "driver_fail_total", "%d", stats.driver_fail_total))) { 2012 return result; 2013 } 2014 if ((result = ecm_state_write(sfi, "driver_fail", "%d", stats.driver_fail))) { 2015 return result; 2016 } 2017 if ((result = ecm_state_write(sfi, "driver_fail_limit", "%d", stats.driver_fail_limit))) { 2018 return result; 2019 } 2020 if ((result = ecm_state_write(sfi, "ae_nack_total", "%d", stats.ae_nack_total))) { 2021 return result; 2022 } 2023 if ((result = ecm_state_write(sfi, "ae_nack", "%d", stats.ae_nack))) { 2024 return result; 2025 } 2026 if ((result = ecm_state_write(sfi, "ae_nack_limit", "%d", stats.ae_nack_limit))) { 2027 return result; 2028 } 2029 2030 return ecm_state_prefix_remove(sfi); 2031} 2032#endif 2033 2034/* 2035 * ecm_nss_multicast_ipv6_connection_instance_alloc() 2036 * Create a front end instance specific for Mcast connection 2037 */ 2038static struct ecm_nss_multicast_ipv6_connection_instance *ecm_nss_multicast_ipv6_connection_instance_alloc( 2039 struct ecm_db_connection_instance *ci, 2040 bool can_accel) 2041{ 2042 struct ecm_nss_multicast_ipv6_connection_instance *nmci; 2043 struct ecm_front_end_connection_instance *feci; 2044 2045 nmci = (struct ecm_nss_multicast_ipv6_connection_instance *)kzalloc(sizeof(struct ecm_nss_multicast_ipv6_connection_instance), GFP_ATOMIC | __GFP_NOWARN); 2046 if (!nmci) { 2047 DEBUG_WARN("Mcast Front end alloc failed\n"); 2048 return NULL; 2049 } 2050 2051 /* 2052 * Refs is 1 for the creator of the connection 2053 */ 2054 feci = (struct ecm_front_end_connection_instance *)nmci; 2055 feci->refs = 1; 2056 DEBUG_SET_MAGIC(nmci, ECM_NSS_MULTICAST_IPV6_CONNECTION_INSTANCE_MAGIC); 2057 spin_lock_init(&feci->lock); 2058 2059 feci->can_accel = can_accel; 2060 feci->accel_mode = (can_accel) ? ECM_FRONT_END_ACCELERATION_MODE_DECEL : ECM_FRONT_END_ACCELERATION_MODE_FAIL_DENIED; 2061 spin_lock_bh(&ecm_nss_ipv6_lock); 2062 feci->stats.no_action_seen_limit = ecm_nss_ipv6_no_action_limit_default; 2063 feci->stats.driver_fail_limit = ecm_nss_ipv6_driver_fail_limit_default; 2064 feci->stats.ae_nack_limit = ecm_nss_ipv6_nack_limit_default; 2065 spin_unlock_bh(&ecm_nss_ipv6_lock); 2066 2067 /* 2068 * Copy reference to connection - no need to ref ci as ci maintains a ref to this instance instead (this instance persists for as long as ci does) 2069 */ 2070 feci->ci = ci; 2071 2072 /* 2073 * Populate the methods and callbacks 2074 */ 2075 feci->ref = ecm_nss_multicast_ipv6_connection_ref; 2076 feci->deref = ecm_nss_multicast_ipv6_connection_deref; 2077 feci->decelerate = ecm_nss_multicast_ipv6_connection_decelerate; 2078 feci->accel_state_get = ecm_nss_multicast_ipv6_connection_accel_state_get; 2079 feci->action_seen = ecm_nss_multicast_ipv6_connection_action_seen; 2080 feci->accel_ceased = ecm_nss_multicast_ipv6_connection_accel_ceased; 2081#ifdef ECM_STATE_OUTPUT_ENABLE 2082 feci->state_get = ecm_nss_multicast_ipv6_connection_state_get; 2083#endif 2084 feci->ae_interface_number_by_dev_get = ecm_nss_common_get_interface_number_by_dev; 2085 2086 return nmci; 2087} 2088 2089/* 2090 * ecm_nss_multicast_ipv6_connection_process() 2091 * Process a UDP Multicast packet 2092 */ 2093unsigned int ecm_nss_multicast_ipv6_connection_process(struct net_device *out_dev, 2094 struct net_device *in_dev, 2095 uint8_t *src_node_addr, 2096 uint8_t *dest_node_addr, 2097 bool can_accel, bool is_routed, struct sk_buff *skb, 2098 struct ecm_tracker_ip_header *iph, 2099 struct nf_conn *ct, ecm_tracker_sender_type_t sender, 2100 struct nf_conntrack_tuple *orig_tuple, struct nf_conntrack_tuple *reply_tuple) 2101{ 2102 struct udphdr *udp_hdr; 2103 struct udphdr udp_hdr_buff; 2104 struct in6_addr origin6; 2105 struct in6_addr group6; 2106 struct ecm_db_multicast_tuple_instance *tuple_instance; 2107 int src_port; 2108 int dest_port; 2109 struct ecm_db_connection_instance *ci; 2110 ecm_db_direction_t ecm_dir = ECM_DB_DIRECTION_NON_NAT; 2111 ip_addr_t match_addr; 2112 struct ecm_classifier_instance *assignments[ECM_CLASSIFIER_TYPES]; 2113 int aci_index; 2114 int32_t mc_if_cnt; 2115 int assignment_count; 2116 ecm_db_timer_group_t ci_orig_timer_group; 2117 struct ecm_classifier_process_response prevalent_pr; 2118 ip_addr_t ip_src_addr; 2119 ip_addr_t ip_dest_addr; 2120 uint32_t mc_dest_if[ECM_DB_MULTICAST_IF_MAX]; 2121 bool br_dev_found_in_mfc = false; 2122 int protocol = (int)orig_tuple->dst.protonum; 2123 2124 if (protocol != IPPROTO_UDP) { 2125 DEBUG_WARN("Invalid Protocol %d in skb %p\n", protocol, skb); 2126 return NF_ACCEPT; 2127 } 2128 2129 /* 2130 * Extract UDP header to obtain port information 2131 */ 2132 udp_hdr = ecm_tracker_udp_check_header_and_read(skb, iph, &udp_hdr_buff); 2133 if (unlikely(!udp_hdr)) { 2134 DEBUG_WARN("Invalid UDP header in skb %p\n", skb); 2135 return NF_ACCEPT; 2136 } 2137 2138 /* 2139 * Return if source dev is any tunnel type 2140 */ 2141 if (in_dev->type == ECM_ARPHRD_IPSEC_TUNNEL_TYPE || 2142 in_dev->type == ARPHRD_SIT || 2143 in_dev->type == ARPHRD_TUNNEL6) { 2144 DEBUG_TRACE("Net device: %p is TUNNEL type: %d\n", in_dev, in_dev->type); 2145 return NF_ACCEPT; 2146 } 2147 2148 /* 2149 * Now extract information, if we have conntrack then use that (which would already be in the tuples) 2150 */ 2151 if (unlikely(!ct)) { 2152 orig_tuple->src.u.udp.port = udp_hdr->source; 2153 orig_tuple->dst.u.udp.port = udp_hdr->dest; 2154 reply_tuple->src.u.udp.port = udp_hdr->dest; 2155 reply_tuple->dst.u.udp.port = udp_hdr->source; 2156 } 2157 2158 /* 2159 * Extract transport port information 2160 * Refer to the ecm_nss_ipv6_process() for information on how we extract this information. 2161 */ 2162 src_port = ntohs(orig_tuple->src.u.udp.port); 2163 dest_port = ntohs(orig_tuple->dst.u.udp.port); 2164 2165 ECM_NIN6_ADDR_TO_IP_ADDR(ip_src_addr, orig_tuple->src.u3.in6); 2166 ECM_NIN6_ADDR_TO_IP_ADDR(ip_dest_addr, orig_tuple->dst.u3.in6); 2167 2168 /* 2169 * Query MFC/Bridge Snooper to access the destination interface list. 2170 */ 2171 ECM_IP_ADDR_TO_NIN6_ADDR(origin6, ip_src_addr); 2172 ECM_IP_ADDR_TO_NIN6_ADDR(group6, ip_dest_addr); 2173 2174 memset(mc_dest_if, 0, sizeof(mc_dest_if)); 2175 2176 mc_if_cnt = ip6mr_find_mfc_entry(&init_net, &origin6, &group6, ECM_DB_MULTICAST_IF_MAX, mc_dest_if); 2177 2178 if (is_routed) { 2179 /* 2180 * This is a routed flow, hence look for a valid MFC rule 2181 */ 2182 if (mc_if_cnt <= 0){ 2183 DEBUG_WARN("Not found a valid vif count %d\n", mc_if_cnt); 2184 return NF_ACCEPT; 2185 } 2186 2187 /* 2188 * Check for the presence of a bridge device in the destination 2189 * interface list given to us by MFC 2190 */ 2191 2192 br_dev_found_in_mfc = ecm_interface_multicast_check_for_br_dev(mc_dest_if, mc_if_cnt); 2193 } else { 2194 if (mc_if_cnt > 0) { 2195 2196 /* 2197 * In case of Bridge + Route there is chance that Bridge post routing hook called first and 2198 * is_route flag is false. To make sure this is a routed flow, query the MFC and if MFC if_cnt 2199 * is not Zero than this is a routed flow. 2200 */ 2201 is_routed = true; 2202 br_dev_found_in_mfc = ecm_interface_multicast_check_for_br_dev(mc_dest_if, mc_if_cnt); 2203 } else { 2204 2205 /* 2206 * Packet flow is pure bridge. Try to query the snooper for the destination 2207 * interface list 2208 */ 2209 mc_if_cnt = mc_bridge_ipv6_get_if(out_dev->master, &origin6, &group6, ECM_DB_MULTICAST_IF_MAX, mc_dest_if); 2210 if (mc_if_cnt <= 0) { 2211 DEBUG_WARN("Not found a valid MCS if count %d\n", mc_if_cnt); 2212 return NF_ACCEPT; 2213 } 2214 } 2215 } 2216 2217 /* 2218 * In pure bridge flow, do not process further if Hop Limit is less than two. 2219 */ 2220 if (!is_routed) { 2221 if (iph->ttl < 2) { 2222 DEBUG_TRACE("%p: Ignoring, Multicast IPv6 Header has Hop Limit one\n", skb); 2223 return NF_ACCEPT; 2224 } 2225 } 2226 2227 DEBUG_TRACE("UDP src: " ECM_IP_ADDR_OCTAL_FMT ":%d, dest: " ECM_IP_ADDR_OCTAL_FMT ":%d\n", 2228 ECM_IP_ADDR_TO_OCTAL(ip_src_addr), src_port, ECM_IP_ADDR_TO_OCTAL(ip_dest_addr), dest_port); 2229 2230 /* 2231 * Look up a connection 2232 */ 2233 ci = ecm_db_connection_find_and_ref(ip_src_addr, ip_dest_addr, IPPROTO_UDP, src_port, dest_port); 2234 2235 /* 2236 * If there is no existing connection then create a new one. 2237 */ 2238 if (unlikely(!ci)) { 2239 struct ecm_db_mapping_instance *src_mi; 2240 struct ecm_db_mapping_instance *dest_mi; 2241 struct ecm_db_node_instance *src_ni; 2242 struct ecm_db_node_instance *dest_ni; 2243 struct ecm_classifier_default_instance *dci; 2244 struct ecm_front_end_connection_instance *feci; 2245 struct ecm_db_connection_instance *nci; 2246 struct ecm_db_iface_instance *from_list[ECM_DB_IFACE_HEIRARCHY_MAX]; 2247 struct ecm_db_iface_instance *to_list; 2248 struct ecm_db_iface_instance *to_list_single; 2249 struct ecm_db_iface_instance *to_list_temp[ECM_DB_IFACE_HEIRARCHY_MAX]; 2250 ecm_classifier_type_t classifier_type; 2251 int32_t *to_list_first; 2252 int32_t *to_first; 2253 int32_t from_list_first; 2254 int32_t interface_idx_cnt = 0; 2255 int vif; 2256 int ret; 2257 char dest_mac_addr[6]; 2258 2259 DEBUG_TRACE("New UDP connection from " ECM_IP_ADDR_OCTAL_FMT ":%u to " ECM_IP_ADDR_OCTAL_FMT ":%u\n", 2260 ECM_IP_ADDR_TO_OCTAL(ip_src_addr), src_port, ECM_IP_ADDR_TO_OCTAL(ip_dest_addr), dest_port); 2261 2262 /* 2263 * Before we attempt to create the connection are we being terminated? 2264 */ 2265 spin_lock_bh(&ecm_nss_ipv6_lock); 2266 if (ecm_nss_ipv6_terminate_pending) { 2267 spin_unlock_bh(&ecm_nss_ipv6_lock); 2268 DEBUG_WARN("Terminating\n"); 2269 2270 /* 2271 * As we are terminating we just allow the packet to pass - it's no longer our concern 2272 */ 2273 return NF_ACCEPT; 2274 } 2275 spin_unlock_bh(&ecm_nss_ipv6_lock); 2276 2277 /* 2278 * Now allocate the new connection 2279 */ 2280 nci = ecm_db_connection_alloc(); 2281 if (!nci) { 2282 DEBUG_WARN("Failed to allocate connection\n"); 2283 return NF_ACCEPT; 2284 } 2285 2286 /* 2287 * Connection must have a front end instance associated with it 2288 */ 2289 feci = (struct ecm_front_end_connection_instance *)ecm_nss_multicast_ipv6_connection_instance_alloc(nci, can_accel); 2290 if (!feci) { 2291 ecm_db_connection_deref(nci); 2292 DEBUG_WARN("Failed to allocate front end\n"); 2293 return NF_ACCEPT; 2294 } 2295 2296 /* 2297 * Create a tuple instance 2298 */ 2299 tuple_instance = ecm_db_multicast_tuple_instance_alloc(ip_src_addr, ip_dest_addr, src_port, dest_port); 2300 if (!tuple_instance) { 2301 ecm_db_connection_deref(nci); 2302 DEBUG_WARN("Failed to allocate tuple instance\n"); 2303 return NF_ACCEPT; 2304 } 2305 /* 2306 * Create Destination MAC address using IP multicast destination address 2307 */ 2308 ecm_translate_multicast_mac(ip_dest_addr, dest_mac_addr); 2309 2310 /* 2311 * Get the src and destination mappings 2312 * For this we also need the interface lists which we also set upon the new connection while we are at it. 2313 * GGG TODO rework terms of "src/dest" - these need to be named consistently as from/to as per database terms. 2314 * GGG TODO The empty list checks should not be needed, mapping_establish_and_ref() should fail out if there is no list anyway. 2315 */ 2316 DEBUG_TRACE("%p: Create the 'from' interface heirarchy list\n", nci); 2317 from_list_first = ecm_interface_heirarchy_construct(feci, from_list, ip_dest_addr, ip_src_addr, 6, IPPROTO_UDP, in_dev, is_routed, in_dev, src_node_addr, dest_node_addr, NULL); 2318 if (from_list_first == ECM_DB_IFACE_HEIRARCHY_MAX) { 2319 feci->deref(feci); 2320 ecm_db_connection_deref(nci); 2321 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2322 DEBUG_WARN("Failed to obtain 'from' heirarchy list\n"); 2323 return NF_ACCEPT; 2324 } 2325 ecm_db_connection_from_interfaces_reset(nci, from_list, from_list_first); 2326 2327 DEBUG_TRACE("%p: Create source node\n", nci); 2328 src_ni = ecm_nss_ipv6_node_establish_and_ref(feci, in_dev, ip_src_addr, from_list, from_list_first, src_node_addr); 2329 ecm_db_connection_interfaces_deref(from_list, from_list_first); 2330 if (!src_ni) { 2331 feci->deref(feci); 2332 ecm_db_connection_deref(nci); 2333 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2334 DEBUG_WARN("Failed to establish source node\n"); 2335 return NF_ACCEPT; 2336 } 2337 2338 DEBUG_TRACE("%p: Create source mapping\n", nci); 2339 src_mi = ecm_nss_ipv6_mapping_establish_and_ref(ip_src_addr, src_port); 2340 if (!src_mi) { 2341 ecm_db_node_deref(src_ni); 2342 feci->deref(feci); 2343 ecm_db_connection_deref(nci); 2344 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2345 DEBUG_WARN("Failed to establish src mapping\n"); 2346 return NF_ACCEPT; 2347 } 2348 2349 DEBUG_TRACE("%p: Create the 'to' interface heirarchy list\n", nci); 2350 2351 to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN); 2352 if (!to_list) { 2353 ecm_db_mapping_deref(src_mi); 2354 ecm_db_node_deref(src_ni); 2355 feci->deref(feci); 2356 ecm_db_connection_deref(nci); 2357 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2358 return NF_ACCEPT; 2359 } 2360 2361 to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN); 2362 if (!to_list_first) { 2363 kfree(to_list); 2364 ecm_db_mapping_deref(src_mi); 2365 ecm_db_node_deref(src_ni); 2366 feci->deref(feci); 2367 ecm_db_connection_deref(nci); 2368 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2369 kfree(to_list); 2370 return NF_ACCEPT; 2371 } 2372 2373 /* 2374 * Create the multicast 'to' interface heirarchy 2375 */ 2376 DEBUG_TRACE("%p: Create the multicast 'to' interface heirarchy list\n", nci); 2377 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 2378 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif); 2379 *to_first = ECM_DB_IFACE_HEIRARCHY_MAX; 2380 } 2381 2382 interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev->master, ip_src_addr, 2383 ip_dest_addr, mc_if_cnt, mc_dest_if, to_list_first, src_node_addr, is_routed); 2384 if (interface_idx_cnt == 0) { 2385 DEBUG_WARN("Failed to obtain 'to' heirarchy list\n"); 2386 ecm_db_mapping_deref(src_mi); 2387 ecm_db_node_deref(src_ni); 2388 feci->deref(feci); 2389 ecm_db_connection_deref(nci); 2390 kfree(to_list); 2391 kfree(to_list_first); 2392 return NF_ACCEPT; 2393 } 2394 2395 ret = ecm_db_multicast_connection_to_interfaces_reset(nci, to_list, to_list_first); 2396 if (ret < 0) { 2397 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 2398 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif); 2399 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 2400 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif); 2401 ecm_db_connection_interfaces_deref(to_list_temp, *to_first); 2402 } 2403 2404 feci->deref(feci); 2405 ecm_db_mapping_deref(src_mi); 2406 ecm_db_node_deref(src_ni); 2407 ecm_db_connection_deref(nci); 2408 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2409 kfree(to_list); 2410 kfree(to_list_first); 2411 DEBUG_WARN("Failed to obtain 'to' heirarchy list\n"); 2412 return NF_ACCEPT; 2413 } 2414 2415 /* 2416 * De-ref the destination interface list 2417 */ 2418 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 2419 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif); 2420 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 2421 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif); 2422 ecm_db_connection_interfaces_deref(to_list_temp, *to_first); 2423 } 2424 2425 DEBUG_TRACE("%p: Create dest node\n", nci); 2426 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list); 2427 dest_ni = ecm_nss_ipv6_node_establish_and_ref(feci, out_dev, ip_dest_addr, to_list_temp, *to_list_first, dest_mac_addr); 2428 if (!dest_ni) { 2429 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 2430 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif); 2431 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 2432 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif); 2433 ecm_db_connection_interfaces_deref(to_list_temp, *to_first); 2434 } 2435 ecm_db_mapping_deref(src_mi); 2436 ecm_db_node_deref(src_ni); 2437 feci->deref(feci); 2438 ecm_db_connection_deref(nci); 2439 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2440 kfree(to_list); 2441 kfree(to_list_first); 2442 DEBUG_WARN("Failed to establish dest node\n"); 2443 return NF_ACCEPT; 2444 } 2445 2446 DEBUG_TRACE("%p: Create dest mapping\n", nci); 2447 dest_mi = ecm_nss_ipv6_mapping_establish_and_ref(ip_dest_addr, dest_port); 2448 if (!dest_mi) { 2449 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 2450 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif); 2451 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 2452 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif); 2453 ecm_db_connection_interfaces_deref(to_list_temp, *to_first); 2454 } 2455 ecm_db_node_deref(dest_ni); 2456 ecm_db_mapping_deref(src_mi); 2457 ecm_db_node_deref(src_ni); 2458 feci->deref(feci); 2459 ecm_db_connection_deref(nci); 2460 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2461 kfree(to_list); 2462 kfree(to_list_first); 2463 DEBUG_WARN("Failed to establish dest mapping\n"); 2464 return NF_ACCEPT; 2465 } 2466 2467 /* 2468 * Every connection also needs a default classifier 2469 */ 2470 dci = ecm_classifier_default_instance_alloc(nci, IPPROTO_UDP, ecm_dir, src_port, dest_port); 2471 if (!dci) { 2472 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 2473 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif); 2474 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 2475 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif); 2476 ecm_db_connection_interfaces_deref(to_list_temp, *to_first); 2477 } 2478 ecm_db_mapping_deref(dest_mi); 2479 ecm_db_node_deref(dest_ni); 2480 ecm_db_mapping_deref(src_mi); 2481 ecm_db_node_deref(src_ni); 2482 feci->deref(feci); 2483 ecm_db_connection_deref(nci); 2484 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2485 kfree(to_list); 2486 kfree(to_list_first); 2487 DEBUG_WARN("Failed to allocate default classifier\n"); 2488 return NF_ACCEPT; 2489 } 2490 ecm_db_connection_classifier_assign(nci, (struct ecm_classifier_instance *)dci); 2491 2492 /* 2493 * Every connection starts with a full complement of classifiers assigned. 2494 * NOTE: Default classifier is a special case considered previously 2495 */ 2496 for (classifier_type = ECM_CLASSIFIER_TYPE_DEFAULT + 1; classifier_type < ECM_CLASSIFIER_TYPES; ++classifier_type) { 2497 struct ecm_classifier_instance *aci = ecm_nss_ipv6_assign_classifier(nci, classifier_type); 2498 if (aci) { 2499 aci->deref(aci); 2500 } else { 2501 dci->base.deref((struct ecm_classifier_instance *)dci); 2502 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 2503 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif); 2504 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 2505 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif); 2506 ecm_db_connection_interfaces_deref(to_list_temp, *to_first); 2507 } 2508 ecm_db_mapping_deref(dest_mi); 2509 ecm_db_node_deref(dest_ni); 2510 ecm_db_mapping_deref(src_mi); 2511 ecm_db_node_deref(src_ni); 2512 feci->deref(feci); 2513 ecm_db_connection_deref(nci); 2514 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2515 kfree(to_list); 2516 kfree(to_list_first); 2517 DEBUG_WARN("Failed to allocate classifiers assignments\n"); 2518 return NF_ACCEPT; 2519 } 2520 } 2521 2522 /* 2523 * Now add the connection into the database. 2524 * NOTE: In an SMP situation such as ours there is a possibility that more than one packet for the same 2525 * connection is being processed simultaneously. 2526 * We *could* end up creating more than one connection instance for the same actual connection. 2527 * To guard against this we now perform a mutex'd lookup of the connection + add once more - another cpu may have created it before us. 2528 */ 2529 spin_lock_bh(&ecm_nss_ipv6_lock); 2530 ci = ecm_db_connection_find_and_ref(ip_src_addr, ip_dest_addr, IPPROTO_UDP, src_port, dest_port); 2531 if (ci) { 2532 /* 2533 * Another cpu created the same connection before us - use the one we just found 2534 */ 2535 spin_unlock_bh(&ecm_nss_ipv6_lock); 2536 for (vif = 0; vif < ECM_DB_MULTICAST_IF_MAX; vif++) { 2537 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, vif); 2538 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 2539 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, vif); 2540 ecm_db_connection_interfaces_deref(to_list_temp, *to_first); 2541 } 2542 2543 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2544 ecm_db_connection_deref(nci); 2545 } else { 2546 struct ecm_tracker_instance *ti; 2547 ecm_db_timer_group_t tg; 2548 ecm_tracker_sender_state_t src_state; 2549 ecm_tracker_sender_state_t dest_state; 2550 ecm_tracker_connection_state_t state; 2551 2552 /* 2553 * Ask tracker for timer group to set the connection to initially. 2554 */ 2555 ti = dci->tracker_get_and_ref(dci); 2556 ti->state_get(ti, &src_state, &dest_state, &state, &tg); 2557 ti->deref(ti); 2558 2559 /* 2560 * Add the new connection we created into the database 2561 * NOTE: assign to a short timer group for now - it is the assigned classifiers responsibility to do this 2562 */ 2563 ecm_db_connection_add(nci, feci, src_mi, dest_mi, src_mi, dest_mi, 2564 src_ni, dest_ni, src_ni, dest_ni, 2565 6, IPPROTO_UDP, ecm_dir, 2566 NULL /* final callback */, 2567 ecm_nss_multicast_ipv6_connection_defunct_callback, 2568 tg, is_routed, nci); 2569 2570 /* 2571 * Add the tuple instance and attach it with connection instance 2572 */ 2573 ecm_db_multicast_tuple_instance_add(tuple_instance, nci); 2574 if (br_dev_found_in_mfc) { 2575 ecm_db_multicast_tuple_instance_flags_set(tuple_instance, ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG); 2576 } 2577 2578 spin_unlock_bh(&ecm_nss_ipv6_lock); 2579 ecm_db_multicast_tuple_instance_deref(tuple_instance); 2580 ci = nci; 2581 DEBUG_INFO("%p: New UDP connection created\n", ci); 2582 } 2583 2584 /* 2585 * No longer need referenecs to the objects we created 2586 */ 2587 dci->base.deref((struct ecm_classifier_instance *)dci); 2588 ecm_db_mapping_deref(dest_mi); 2589 ecm_db_node_deref(dest_ni); 2590 ecm_db_mapping_deref(src_mi); 2591 ecm_db_node_deref(src_ni); 2592 feci->deref(feci); 2593 kfree(to_list); 2594 kfree(to_list_first); 2595 2596 } else { 2597 bool is_dest_interface_list_empty; 2598 2599 /* 2600 * At this pont the feci->accel_mode is ECM_FRONT_END_ACCELERATION_MODE_DEACCEL because the 2601 * MC connection has expired and we had received a callback from MFC which had freed the 2602 * multicast destination interface heirarchy. In this case, we reconstruct the multicast 2603 * destination interface heirarchy and re-accelerate the connection. 2604 */ 2605 is_dest_interface_list_empty = ecm_db_multicast_connection_to_interfaces_set_check(ci); 2606 if (!is_dest_interface_list_empty) { 2607 struct ecm_db_iface_instance *to_list; 2608 struct ecm_db_iface_instance *to_list_temp[ECM_DB_IFACE_HEIRARCHY_MAX]; 2609 struct ecm_db_iface_instance *to_list_single; 2610 int32_t *to_list_first; 2611 int32_t *to_first; 2612 int32_t i, interface_idx_cnt; 2613 int ret; 2614 struct ecm_front_end_connection_instance *feci; 2615 2616 to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN); 2617 if (!to_list) { 2618 ecm_db_connection_deref(ci); 2619 return NF_ACCEPT; 2620 } 2621 2622 to_list_first = (int32_t *)kzalloc(sizeof(int32_t *) * ECM_DB_MULTICAST_IF_MAX, GFP_ATOMIC | __GFP_NOWARN); 2623 if (!to_list_first) { 2624 ecm_db_connection_deref(ci); 2625 kfree(to_list); 2626 return NF_ACCEPT; 2627 } 2628 2629 for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) { 2630 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, i); 2631 *to_first = ECM_DB_IFACE_HEIRARCHY_MAX; 2632 } 2633 2634 feci = ecm_db_connection_front_end_get_and_ref(ci); 2635 interface_idx_cnt = ecm_nss_multicast_ipv6_interface_heirarchy_construct(feci, to_list, in_dev, out_dev->master,\ 2636 ip_src_addr, ip_dest_addr, mc_if_cnt,\ 2637 mc_dest_if, to_list_first, src_node_addr, is_routed); 2638 feci->deref(feci); 2639 if (interface_idx_cnt == 0) { 2640 DEBUG_WARN("Failed to reconstruct 'to mc' heirarchy list\n"); 2641 ecm_db_connection_deref(ci); 2642 kfree(to_list); 2643 kfree(to_list_first); 2644 return NF_ACCEPT; 2645 } 2646 2647 ret = ecm_db_multicast_connection_to_interfaces_reset(ci, to_list, to_list_first); 2648 2649 /* 2650 * De-ref the destination interface list 2651 */ 2652 for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) { 2653 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, i); 2654 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 2655 to_first = ecm_db_multicast_if_first_get_at_index(to_list_first, i); 2656 ecm_db_connection_interfaces_deref(to_list_temp, *to_first); 2657 } 2658 2659 kfree(to_list); 2660 kfree(to_list_first); 2661 2662 /* 2663 * If ret is less than zero than connection reset could not find memory for 2664 * to_mcast_interfaces. Deref the CI and retrun. 2665 */ 2666 if (ret < 0) { 2667 ecm_db_connection_deref(ci); 2668 return NF_ACCEPT; 2669 } 2670 } 2671 } 2672 2673 /* 2674 * Keep connection alive as we have seen activity 2675 */ 2676 if (!ecm_db_connection_defunct_timer_touch(ci)) { 2677 ecm_db_connection_deref(ci); 2678 return NF_ACCEPT; 2679 } 2680 2681 /* 2682 * Identify which side of the connection is sending 2683 */ 2684 ecm_db_connection_from_address_get(ci, match_addr); 2685 if (ECM_IP_ADDR_MATCH(ip_src_addr, match_addr)) { 2686 sender = ECM_TRACKER_SENDER_TYPE_SRC; 2687 } else { 2688 sender = ECM_TRACKER_SENDER_TYPE_DEST; 2689 } 2690 2691 /* 2692 * Do we need to action generation change? 2693 */ 2694 if (unlikely(ecm_db_connection_regeneration_required_check(ci))) { 2695 ecm_nss_multicast_ipv6_connection_regenerate(ci, sender, out_dev, in_dev); 2696 } 2697 2698 /* 2699 * Iterate the assignments and call to process! 2700 * Policy implemented: 2701 * 1. Classifiers that say they are not relevant are unassigned and not actioned further. 2702 * 2. Any drop command from any classifier is honoured. 2703 * 3. All classifiers must action acceleration for accel to be honoured, any classifiers not sure of their relevance will stop acceleration. 2704 * 4. Only the highest priority classifier, that actions it, will have its qos tag honoured. 2705 * 5. Only the highest priority classifier, that actions it, will have its timer group honoured. 2706 */ 2707 DEBUG_TRACE("%p: process begin, skb: %p\n", ci, skb); 2708 prevalent_pr.drop = false; 2709 prevalent_pr.flow_qos_tag = skb->priority; 2710 prevalent_pr.return_qos_tag = skb->priority; 2711 prevalent_pr.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_ACCEL; 2712 prevalent_pr.timer_group = ci_orig_timer_group = ecm_db_connection_timer_group_get(ci); 2713 prevalent_pr.process_actions = 0; 2714 assignment_count = ecm_db_connection_classifier_assignments_get_and_ref(ci, assignments); 2715 for (aci_index = 0; aci_index < assignment_count; ++aci_index) { 2716 struct ecm_classifier_process_response aci_pr; 2717 struct ecm_classifier_instance *aci; 2718 2719 aci = assignments[aci_index]; 2720 DEBUG_TRACE("%p: process: %p, type: %d\n", ci, aci, aci->type_get(aci)); 2721 aci->process(aci, sender, iph, skb, &aci_pr); 2722 DEBUG_TRACE("%p: aci_pr: process actions: %x, became relevant: %u, relevance: %d, drop: %d, " 2723 "flow_qos_tag: %u, return_qos_tag: %u, accel_mode: %x, timer_group: %d\n", 2724 ci, aci_pr.process_actions, aci_pr.became_relevant, aci_pr.relevance, aci_pr.drop, 2725 aci_pr.flow_qos_tag, aci_pr.return_qos_tag, aci_pr.accel_mode, aci_pr.timer_group); 2726 2727 if (aci_pr.relevance == ECM_CLASSIFIER_RELEVANCE_NO) { 2728 ecm_classifier_type_t aci_type; 2729 2730 /* 2731 * This classifier can be unassigned - PROVIDED it is not the default classifier 2732 */ 2733 aci_type = aci->type_get(aci); 2734 if (aci_type == ECM_CLASSIFIER_TYPE_DEFAULT) { 2735 continue; 2736 } 2737 2738 DEBUG_INFO("%p: Classifier not relevant, unassign: %d", ci, aci_type); 2739 ecm_db_connection_classifier_unassign(ci, aci); 2740 continue; 2741 } 2742 2743 /* 2744 * Yes or Maybe relevant. 2745 */ 2746 if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DROP) { 2747 /* 2748 * Drop command from any classifier is actioned. 2749 */ 2750 DEBUG_TRACE("%p: wants drop: %p, type: %d, skb: %p\n", ci, aci, aci->type_get(aci), skb); 2751 prevalent_pr.drop |= aci_pr.drop; 2752 } 2753 2754 /* 2755 * Accel mode permission 2756 */ 2757 if (aci_pr.relevance == ECM_CLASSIFIER_RELEVANCE_MAYBE) { 2758 /* 2759 * Classifier not sure of its relevance - cannot accel yet 2760 */ 2761 DEBUG_TRACE("%p: accel denied by maybe: %p, type: %d\n", ci, aci, aci->type_get(aci)); 2762 prevalent_pr.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO; 2763 } else { 2764 if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_ACCEL_MODE) { 2765 if (aci_pr.accel_mode == ECM_CLASSIFIER_ACCELERATION_MODE_NO) { 2766 DEBUG_TRACE("%p: accel denied: %p, type: %d\n", ci, aci, aci->type_get(aci)); 2767 prevalent_pr.accel_mode = ECM_CLASSIFIER_ACCELERATION_MODE_NO; 2768 } 2769 /* else yes or don't care about accel */ 2770 } 2771 } 2772 2773 /* 2774 * Timer group (the last classifier i.e. the highest priority one) will 'win' 2775 */ 2776 if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_TIMER_GROUP) { 2777 DEBUG_TRACE("%p: timer group: %p, type: %d, group: %d\n", ci, aci, aci->type_get(aci), aci_pr.timer_group); 2778 prevalent_pr.timer_group = aci_pr.timer_group; 2779 } 2780 2781 /* 2782 * Qos tag (the last classifier i.e. the highest priority one) will 'win' 2783 */ 2784 if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_QOS_TAG) { 2785 DEBUG_TRACE("%p: aci: %p, type: %d, flow qos tag: %u, return qos tag: %u\n", 2786 ci, aci, aci->type_get(aci), aci_pr.flow_qos_tag, aci_pr.return_qos_tag); 2787 prevalent_pr.flow_qos_tag = aci_pr.flow_qos_tag; 2788 prevalent_pr.return_qos_tag = aci_pr.return_qos_tag; 2789 } 2790 2791 /* 2792 * If any classifier denied DSCP remarking then that overrides every classifier 2793 */ 2794 if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DSCP_DENY) { 2795 DEBUG_TRACE("%p: aci: %p, type: %d, DSCP remark denied\n", 2796 ci, aci, aci->type_get(aci)); 2797 prevalent_pr.process_actions |= ECM_CLASSIFIER_PROCESS_ACTION_DSCP_DENY; 2798 prevalent_pr.process_actions &= ~ECM_CLASSIFIER_PROCESS_ACTION_DSCP; 2799 } 2800 2801 /* 2802 * DSCP remark action, but only if it has not been denied by any classifier 2803 */ 2804 if (aci_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DSCP) { 2805 if (!(prevalent_pr.process_actions & ECM_CLASSIFIER_PROCESS_ACTION_DSCP_DENY)) { 2806 DEBUG_TRACE("%p: aci: %p, type: %d, DSCP remark wanted, flow_dscp: %u, return dscp: %u\n", 2807 ci, aci, aci->type_get(aci), aci_pr.flow_dscp, aci_pr.return_dscp); 2808 prevalent_pr.process_actions |= ECM_CLASSIFIER_PROCESS_ACTION_DSCP; 2809 prevalent_pr.flow_dscp = aci_pr.flow_dscp; 2810 prevalent_pr.return_dscp = aci_pr.return_dscp; 2811 } 2812 } 2813 } 2814 ecm_db_connection_assignments_release(assignment_count, assignments); 2815 2816 /* 2817 * Change timer group? 2818 */ 2819 if (ci_orig_timer_group != prevalent_pr.timer_group) { 2820 DEBUG_TRACE("%p: change timer group from: %d to: %d\n", ci, ci_orig_timer_group, prevalent_pr.timer_group); 2821 ecm_db_connection_defunct_timer_reset(ci, prevalent_pr.timer_group); 2822 } 2823 2824 /* 2825 * Drop? 2826 */ 2827 if (prevalent_pr.drop) { 2828 DEBUG_TRACE("%p: drop: %p\n", ci, skb); 2829 ecm_db_connection_data_totals_update_dropped(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1); 2830 ecm_db_connection_deref(ci); 2831 return NF_ACCEPT; 2832 } 2833 ecm_db_connection_data_totals_update(ci, (sender == ECM_TRACKER_SENDER_TYPE_SRC)? true : false, skb->len, 1); 2834 2835 /* 2836 * Assign qos tag 2837 * GGG TODO Should we use sender to identify whether to use flow or return qos tag? 2838 */ 2839 skb->priority = prevalent_pr.flow_qos_tag; 2840 DEBUG_TRACE("%p: skb priority: %u\n", ci, skb->priority); 2841 2842 /* 2843 * Accelerate? 2844 */ 2845 if (prevalent_pr.accel_mode == ECM_CLASSIFIER_ACCELERATION_MODE_ACCEL) { 2846 struct ecm_front_end_connection_instance *feci; 2847 DEBUG_TRACE("%p: accel\n", ci); 2848 feci = ecm_db_connection_front_end_get_and_ref(ci); 2849 ecm_nss_multicast_ipv6_connection_accelerate(feci, &prevalent_pr); 2850 feci->deref(feci); 2851 } else { 2852 goto done; 2853 } 2854done: 2855 ecm_db_connection_deref(ci); 2856 return NF_ACCEPT; 2857} 2858 2859/* 2860 * ecm_nss_multicast_ipv6_br_update_event_callback() 2861 * Callback received from bridge multicast snooper module in the 2862 * following events: 2863 * a.) Updates to a muticast group due to IGMP JOIN/LEAVE. 2864 * 2865 * group: IP multicast group address 2866 * brdev: bridge netdevice 2867 * 2868 * This function does the following: 2869 * a.) Lookup the tuple_instance table to find any flows through the bridge for the group 2870 * b.) Query the MCS bridge using the source and group address, to receive a list 2871 * of bridge slaves for the flow 2872 * c.) Process the updates by matching the received bridge slave list with existing 2873 * destination interfaces heirarchy for the CI, and decide whether to delete an 2874 * exiting interface heirarchy or add a new heirarchy. 2875 */ 2876static void ecm_nss_multicast_ipv6_br_update_event_callback(struct net_device *brdev, struct in6_addr *group) 2877{ 2878 struct ecm_db_multicast_tuple_instance *tuple_instance; 2879 struct ecm_db_multicast_tuple_instance *tuple_instance_next; 2880 struct ecm_db_connection_instance *ci; 2881 struct ecm_front_end_connection_instance *feci; 2882 struct ecm_db_iface_instance *to_list; 2883 struct ecm_db_iface_instance *to_list_single; 2884 struct ecm_db_iface_instance *to_list_temp[ECM_DB_IFACE_HEIRARCHY_MAX]; 2885 struct ecm_multicast_if_update mc_sync; 2886 ip_addr_t dest_ip; 2887 ip_addr_t grp_ip; 2888 ip_addr_t src_ip; 2889 struct in6_addr group6; 2890 struct in6_addr origin6; 2891 uint8_t src_node_addr[ETH_ALEN]; 2892 int32_t to_list_first[ECM_DB_MULTICAST_IF_MAX]; 2893 int i, ret; 2894 uint32_t if_cnt, mc_flags = 0; 2895 bool mc_update; 2896 int32_t if_num; 2897 uint32_t mc_max_dst = ECM_DB_MULTICAST_IF_MAX; 2898 uint32_t mc_dst_dev[ECM_DB_MULTICAST_IF_MAX]; 2899 2900 2901 memcpy(&group6, group, sizeof(struct in6_addr)); 2902 ECM_NIN6_ADDR_TO_IP_ADDR(dest_ip, group6); 2903 2904 DEBUG_TRACE("IP dst: " ECM_IP_ADDR_OCTAL_FMT , ECM_IP_ADDR_TO_OCTAL(dest_ip)); 2905 2906 /* 2907 * Get the first entry for the group in the tuple_instance table 2908 */ 2909 tuple_instance = ecm_db_multicast_connection_get_and_ref_first(dest_ip); 2910 if (!tuple_instance) { 2911 DEBUG_TRACE("tuple info not found\n"); 2912 return; 2913 } 2914 2915 while (tuple_instance) { 2916 /* 2917 * We now have a 5-tuple which has been accelerated. Query the MCS bridge to receive a list 2918 * of interfaces left or joined a group for a source. 2919 */ 2920 memset(mc_dst_dev, 0, sizeof(mc_dst_dev)); 2921 2922 /* 2923 * Get the group IP address stored in tuple_instance and match this with 2924 * the group IP received from MCS update callback. 2925 */ 2926 ecm_db_multicast_tuple_instance_group_ip_get(tuple_instance, grp_ip); 2927 if (!ECM_IP_ADDR_MATCH(grp_ip, dest_ip)) { 2928 tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance); 2929 ecm_db_multicast_connection_deref(tuple_instance); 2930 tuple_instance = tuple_instance_next; 2931 continue; 2932 } 2933 2934 /* 2935 * Get the source IP address for this entry for the group 2936 */ 2937 ecm_db_multicast_tuple_instance_source_ip_get(tuple_instance, src_ip); 2938 ECM_IP_ADDR_TO_NIN6_ADDR(origin6, src_ip); 2939 2940 /* 2941 * Query bridge snooper for the destination list when given the group and source 2942 * if, if_num < 0 mc_bridge_ipv6_get_if has encountered with some error, return immediately 2943 * if_num = 0 All slaves has left the group. Deacel the flow. 2944 * if_num > 0 An interface leave/Join the group. Process the leave/join interface request. 2945 */ 2946 if_num = mc_bridge_ipv6_get_if (brdev, &origin6, &group6, mc_max_dst, mc_dst_dev); 2947 if (if_num < 0) { 2948 DEBUG_TRACE("No valid bridge slaves for the group/source\n"); 2949 2950 /* 2951 * This may a valid case when all the interface has left a multicast group. 2952 * In this case the MCS will return if_num 0, But we may have an oudated 2953 * interface in multicast interface heirarchy list. At next step we have to 2954 * check whether the DB instance is present or not. 2955 */ 2956 tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance); 2957 ecm_db_multicast_connection_deref(tuple_instance); 2958 tuple_instance = tuple_instance_next; 2959 continue; 2960 } 2961 2962 /* 2963 * Get a DB connection instance for the 5-tuple 2964 */ 2965 ci = ecm_db_multicast_connection_get_from_tuple(tuple_instance); 2966 2967 /* 2968 * All bridge slaves has left the group. If flow is pure bridge, Deacel the connection and return. 2969 * If flow is routed, let MFC callback handle this. 2970 */ 2971 if (if_num == 0) { 2972 bool is_routed; 2973 2974 is_routed = ecm_db_connection_is_routed_get(ci); 2975 2976 /* 2977 * If there are no routed interfaces, then decelerate. Else 2978 * we let MFC update callback handle this 2979 */ 2980 if (!is_routed) { 2981 /* 2982 * Decelerate the flow 2983 */ 2984 feci = ecm_db_connection_front_end_get_and_ref(ci); 2985 feci->decelerate(feci); 2986 feci->deref(feci); 2987 2988 /* 2989 * Get next multicast connection instance 2990 */ 2991 tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance); 2992 ecm_db_multicast_connection_deref(tuple_instance); 2993 tuple_instance = tuple_instance_next; 2994 continue; 2995 } 2996 2997 ecm_db_multicast_connection_deref(tuple_instance); 2998 return; 2999 } 3000 3001 feci = ecm_db_connection_front_end_get_and_ref(ci); 3002 3003 DEBUG_TRACE("MCS-cb: src_ip = 0x%x, dest_ip = 0x%x, Num if = %d\n", src_ip[0], dest_ip[0], if_num); 3004 3005 memset(&mc_sync, 0, sizeof(mc_sync)); 3006 spin_lock_bh(&ecm_nss_ipv6_lock); 3007 3008 /* 3009 * Find out changes to the destination interfaces heirarchy 3010 * of the connection. We try to find out the interfaces that 3011 * have joined new, and the existing interfaces in the list 3012 * that have left seperately. 3013 */ 3014 mc_update = ecm_interface_multicast_find_updates_to_iface_list(ci, &mc_sync, mc_flags, true, mc_dst_dev, if_num); 3015 if (!mc_update) { 3016 3017 /* 3018 * No updates to this multicast flow. Move on to the next 3019 * flow for the same group 3020 */ 3021 spin_unlock_bh(&ecm_nss_ipv6_lock); 3022 tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance); 3023 ecm_db_multicast_connection_deref(tuple_instance); 3024 tuple_instance = tuple_instance_next; 3025 continue; 3026 } 3027 3028 spin_unlock_bh(&ecm_nss_ipv6_lock); 3029 DEBUG_TRACE("BRIDGE UPDATE callback ===> leave_cnt %d, join_cnt %d\n", mc_sync.if_leave_cnt, mc_sync.if_join_cnt); 3030 3031 /* 3032 * Do we have any new interfaces that have joined? 3033 */ 3034 if (mc_sync.if_join_cnt > 0) { 3035 to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN); 3036 if (!to_list) { 3037 feci->deref(feci); 3038 ecm_db_multicast_connection_deref(tuple_instance); 3039 return; 3040 } 3041 3042 /* 3043 * Initialize the heirarchy's indices for the 'to_list' 3044 * which will hold the interface heirarchies for the new joinees 3045 */ 3046 for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) { 3047 to_list_first[i] = ECM_DB_IFACE_HEIRARCHY_MAX; 3048 } 3049 3050 ecm_db_connection_from_node_address_get(ci, src_node_addr); 3051 3052 /* 3053 * Create the interface heirarchy list for the new interfaces. We append this list later to 3054 * the existing list of destination interfaces. 3055 */ 3056 if_cnt = ecm_interface_multicast_heirarchy_construct_bridged(feci, to_list, brdev, src_ip, dest_ip, mc_sync.if_join_cnt, mc_sync.join_dev, to_list_first, src_node_addr, NULL); 3057 if (if_cnt == 0) { 3058 DEBUG_WARN("Failed to obtain 'to_mcast_update' heirarchy list\n"); 3059 feci->deref(feci); 3060 ecm_db_multicast_connection_deref(tuple_instance); 3061 kfree(to_list); 3062 break; 3063 } 3064 3065 /* 3066 * Append the interface heirarchy array of the new joinees to the existing destination list 3067 */ 3068 ecm_db_multicast_connection_to_interfaces_update(ci, to_list, to_list_first, mc_sync.if_join_idx); 3069 3070 /* 3071 * De-ref the updated destination interface list 3072 */ 3073 for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) { 3074 if (mc_sync.if_join_idx[i]) { 3075 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, i); 3076 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 3077 ecm_db_connection_interfaces_deref(to_list_temp, to_list_first[i]); 3078 } 3079 } 3080 kfree(to_list); 3081 } 3082 3083 /* 3084 * Push the updates to NSS 3085 */ 3086 DEBUG_TRACE("%p: Update accel\n", ci); 3087 if ((feci->accel_mode <= ECM_FRONT_END_ACCELERATION_MODE_FAIL_DENIED) || 3088 (feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_ACCEL)) { 3089 DEBUG_TRACE("%p: Ignoring wrong mode accel for conn: %p\n", feci, feci->ci); 3090 feci->deref(feci); 3091 ecm_db_multicast_connection_deref(tuple_instance); 3092 return; 3093 } 3094 3095 ret = ecm_nss_multicast_ipv6_connection_update_accelerate(feci, &mc_sync); 3096 if (ret < 0) { 3097 feci->decelerate(feci); 3098 feci->deref(feci); 3099 ecm_db_multicast_connection_deref(tuple_instance); 3100 return; 3101 } 3102 3103 feci->deref(feci); 3104 3105 /* 3106 * Release the interfaces that may have left the connection 3107 */ 3108 for (i = 0; i < ECM_DB_MULTICAST_IF_MAX && mc_sync.if_leave_cnt; i++) { 3109 3110 /* 3111 * Is this entry marked? If yes, then the corresponding entry 3112 * in the 'to_mcast_interfaces' array in the ci has left the 3113 * connection 3114 */ 3115 if (mc_sync.if_leave_idx[i]) { 3116 3117 /* 3118 * Release the interface heirarchy for this 3119 * interface since it has left the group 3120 */ 3121 ecm_db_multicast_connection_to_interfaces_clear_at_index(ci, i); 3122 mc_sync.if_leave_cnt--; 3123 } 3124 } 3125 3126 tuple_instance_next = ecm_db_multicast_connection_get_and_ref_next(tuple_instance); 3127 ecm_db_multicast_connection_deref(tuple_instance); 3128 tuple_instance = tuple_instance_next; 3129 } 3130 3131 return; 3132} 3133 3134/* 3135 * ecm_nss_multicast_ipv6_mfc_update_event_callback() 3136 * Callback called by Linux kernel multicast routing module in the 3137 * following events: 3138 * a.) Updates to destination interface lists for a multicast route due to 3139 * IGMP JOIN/LEAVE 3140 * b.) Multicast route delete event 3141 * 3142 * group: IP multicast group address 3143 * origin: IP source for the multicast route 3144 * to_dev_idx[]: Array of ifindex for destination interfaces for the route 3145 * max_to_dev: size of the array 3146 * op: UPDATE or DELETE event 3147 * 3148 * This function does the following: 3149 * a.) Lookup the tuple_instance table to find any accelerated flows for the group/source, 3150 * and access their CI 3151 * b.) Process the updates by matching the received destination interface list with existing 3152 * destination interfaces heirarchy for the CI, and decide whether to delete an 3153 * exiting interface heirarchy or add a new heirarchy. 3154 */ 3155static void ecm_nss_multicast_ipv6_mfc_update_event_callback(struct in6_addr *group, struct in6_addr *origin, uint32_t max_to_dev, uint32_t to_dev_idx[], uint8_t op) 3156{ 3157 struct ecm_db_connection_instance *ci; 3158 struct ecm_db_multicast_tuple_instance *tuple_instance; 3159 struct ecm_multicast_if_update mc_sync; 3160 struct in6_addr origin6; 3161 struct in6_addr group6; 3162 int32_t vif_cnt; 3163 ip_addr_t src_ip; 3164 ip_addr_t dest_ip; 3165 3166 memcpy(&origin6, origin, sizeof(ip_addr_t)); 3167 memcpy(&group6, group, sizeof(ip_addr_t)); 3168 3169 ECM_NIN6_ADDR_TO_IP_ADDR(src_ip, origin6); 3170 ECM_NIN6_ADDR_TO_IP_ADDR(dest_ip, group6); 3171 3172 DEBUG_TRACE("IP Packet src: " ECM_IP_ADDR_OCTAL_FMT "dst: " ECM_IP_ADDR_OCTAL_FMT , 3173 ECM_IP_ADDR_TO_OCTAL(src_ip),ECM_IP_ADDR_TO_OCTAL(dest_ip)); 3174 3175 /* 3176 * Access the 5-tuple information from the tuple_instance table, using the 3177 * source and group addresses 3178 */ 3179 tuple_instance = ecm_db_multicast_connection_find_and_ref(src_ip, dest_ip); 3180 if (!tuple_instance) { 3181 DEBUG_TRACE("MFC_EVENT: Port info is not found\n"); 3182 return; 3183 } 3184 3185 /* 3186 * Get the DB connection instance using the tuple_instance 3187 */ 3188 ci = ecm_db_multicast_connection_get_from_tuple(tuple_instance); 3189 3190 DEBUG_TRACE("%p: Multicast conn\n", ci); 3191 3192 memset(&mc_sync, 0, sizeof(mc_sync)); 3193 3194 switch (op) { 3195 case IP6MR_MFC_EVENT_UPDATE: 3196 { 3197 struct ecm_front_end_connection_instance *feci; 3198 struct ecm_db_iface_instance *to_list; 3199 struct ecm_db_iface_instance *to_list_single; 3200 struct ecm_db_iface_instance *to_list_temp[ECM_DB_IFACE_HEIRARCHY_MAX]; 3201 uint32_t to_list_first[ECM_DB_MULTICAST_IF_MAX]; 3202 uint32_t i, ret; 3203 uint32_t mc_flags = 0; 3204 bool br_present_in_dest_dev_list = false; 3205 bool mc_update = false; 3206 3207 /* 3208 * Check if this multicast connection has a bridge 3209 * device in multicast destination interface list. 3210 */ 3211 mc_flags = ecm_db_multicast_tuple_instance_flags_get(tuple_instance); 3212 if (br_present_in_dest_dev_list & ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG) { 3213 mc_flags |= ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG; 3214 } 3215 3216 spin_lock_bh(&ecm_nss_ipv6_lock); 3217 3218 /* 3219 * Find out changes to the destination interfaces heirarchy 3220 * of the connection. We try to find out the interfaces that 3221 * have joined new, and the existing interfaces in the list 3222 * that have left seperately. 3223 */ 3224 mc_update = ecm_interface_multicast_find_updates_to_iface_list(ci, &mc_sync, mc_flags, false, to_dev_idx, max_to_dev); 3225 if (!mc_update) { 3226 spin_unlock_bh(&ecm_nss_ipv6_lock); 3227 ecm_db_multicast_connection_deref(tuple_instance); 3228 return; 3229 } 3230 3231 br_present_in_dest_dev_list = ecm_interface_multicast_check_for_br_dev(mc_sync.join_dev, mc_sync.if_join_cnt); 3232 if (!br_present_in_dest_dev_list) { 3233 ecm_db_multicast_tuple_instance_flags_set(tuple_instance, ~ECM_DB_MULTICAST_CONNECTION_BRIDGE_DEV_SET_FLAG); 3234 } 3235 3236 spin_unlock_bh(&ecm_nss_ipv6_lock); 3237 DEBUG_TRACE("%p: MFC update callback ===> leave_cnt %d, join_cnt %d\n", ci, mc_sync.if_leave_cnt, mc_sync.if_join_cnt); 3238 3239 feci = ecm_db_connection_front_end_get_and_ref(ci); 3240 3241 /* 3242 * Do we have any new interfaces that have joined? 3243 */ 3244 if (mc_sync.if_join_cnt > 0) { 3245 to_list = (struct ecm_db_iface_instance *)kzalloc(ECM_DB_TO_MCAST_INTERFACES_SIZE, GFP_ATOMIC | __GFP_NOWARN); 3246 if (!to_list) { 3247 feci->deref(feci); 3248 ecm_db_multicast_connection_deref(tuple_instance); 3249 return; 3250 } 3251 3252 /* 3253 * Initialize the heirarchy's indices for the 'to_list' 3254 * which will hold the interface heirarchies for the new joinees 3255 */ 3256 for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) { 3257 to_list_first[i] = ECM_DB_IFACE_HEIRARCHY_MAX; 3258 } 3259 3260 /* 3261 * Create the interface heirarchy list for the new interfaces. We append this list later to 3262 * the existing list of destination interfaces. 3263 */ 3264 vif_cnt = ecm_interface_multicast_heirarchy_construct_routed(feci, to_list, NULL, src_ip, dest_ip, mc_sync.if_join_cnt, mc_sync.join_dev, to_list_first, NULL); 3265 if (vif_cnt == 0) { 3266 DEBUG_WARN("Failed to obtain 'to_mcast_update' heirarchy list\n"); 3267 feci->deref(feci); 3268 ecm_db_multicast_connection_deref(tuple_instance); 3269 kfree(to_list); 3270 return; 3271 } 3272 3273 /* 3274 * Append the interface heirarchy array of the new joinees to the existing destination list 3275 */ 3276 ecm_db_multicast_connection_to_interfaces_update(ci, to_list, to_list_first, mc_sync.if_join_idx); 3277 3278 /* 3279 * De-ref the updated destination interface list 3280 */ 3281 for (i = 0; i < ECM_DB_MULTICAST_IF_MAX; i++) { 3282 if (mc_sync.if_join_idx[i]) { 3283 to_list_single = ecm_db_multicast_if_heirarchy_get(to_list, i); 3284 ecm_db_multicast_copy_if_heirarchy(to_list_temp, to_list_single); 3285 ecm_db_connection_interfaces_deref(to_list_temp, to_list_first[i]); 3286 } 3287 } 3288 kfree(to_list); 3289 } 3290 3291 /* 3292 * Push the updates to NSS 3293 */ 3294 DEBUG_TRACE("%p: Update accel\n", ci); 3295 if ((feci->accel_mode <= ECM_FRONT_END_ACCELERATION_MODE_FAIL_DENIED) || 3296 (feci->accel_mode != ECM_FRONT_END_ACCELERATION_MODE_ACCEL)) { 3297 DEBUG_TRACE("%p: Ignoring wrong mode accel for conn: %p\n", feci, feci->ci); 3298 feci->deref(feci); 3299 ecm_db_multicast_connection_deref(tuple_instance); 3300 return; 3301 } 3302 3303 /* 3304 * Update the new rules in FW. If returns error decelerate the connection 3305 * and flush all ECM rules. 3306 */ 3307 ret = ecm_nss_multicast_ipv6_connection_update_accelerate(feci, &mc_sync); 3308 if (ret < 0) { 3309 feci->decelerate(feci); 3310 feci->deref(feci); 3311 ecm_db_multicast_connection_deref(tuple_instance); 3312 return; 3313 } 3314 3315 feci->deref(feci); 3316 3317 /* 3318 * Release the interfaces that may have left the connection 3319 */ 3320 for (i = 0; i < ECM_DB_MULTICAST_IF_MAX && mc_sync.if_leave_cnt; i++) { 3321 3322 /* 3323 * Is this entry marked? If yes, then the corresponding entry 3324 * in the 'to_mcast_interfaces' array in the ci has left the 3325 * connection 3326 */ 3327 if (mc_sync.if_leave_idx[i]) { 3328 3329 /* 3330 * Release the interface heirarchy for this 3331 * interface since it has left the group 3332 */ 3333 ecm_db_multicast_connection_to_interfaces_clear_at_index(ci, i); 3334 mc_sync.if_leave_cnt--; 3335 } 3336 } 3337 3338 ecm_db_multicast_connection_deref(tuple_instance); 3339 break; 3340 } 3341 case IP6MR_MFC_EVENT_DELETE: 3342 { 3343 struct ecm_front_end_connection_instance *feci; 3344 3345 /* 3346 * MFC reports that the multicast connection has died. 3347 * Now we can Decelerate connection and free the frontend instance 3348 */ 3349 DEBUG_TRACE("MFC callback ===> delete all entry\n"); 3350 3351 /* 3352 * Get the front end instance 3353 */ 3354 feci = ecm_db_connection_front_end_get_and_ref(ci); 3355 feci->decelerate(feci); 3356 feci->deref(feci); 3357 ecm_db_multicast_connection_deref(tuple_instance); 3358 break; 3359 } 3360 default: 3361 DEBUG_TRACE("Wrong op, shouldn't be here\n"); 3362 break; 3363 } 3364 3365 return; 3366} 3367 3368/* 3369 * ecm_nss_multicast_ipv6_debugfs_init() 3370 */ 3371bool ecm_nss_multicast_ipv6_debugfs_init(struct dentry *dentry) 3372{ 3373 struct dentry *multicast_dentry; 3374 3375 multicast_dentry = debugfs_create_u32("multicast_accelerated_count", S_IRUGO, dentry, 3376 &ecm_nss_multicast_ipv6_accelerated_count); 3377 if (!multicast_dentry) { 3378 DEBUG_ERROR("Failed to create ecm nss ipv6 multicast_accelerated_count file in debugfs\n"); 3379 return false; 3380 } 3381 3382 return true; 3383} 3384 3385/* 3386 * ecm_nss_multicast_ipv6_init() 3387 * Register the callbacks for MCS snooper and MFC update 3388 */ 3389void ecm_nss_multicast_ipv6_init(void) 3390{ 3391 /* 3392 * Register multicast update callback to MCS snooper 3393 */ 3394 mc_bridge_ipv6_update_callback_register(ecm_nss_multicast_ipv6_br_update_event_callback); 3395 3396 /* 3397 * Register multicast update callbacks to MFC 3398 */ 3399 ip6mr_register_mfc_event_offload_callback(ecm_nss_multicast_ipv6_mfc_update_event_callback); 3400} 3401 3402/* 3403 * ecm_nss_multicast_ipv6_exit() 3404 * De-register the callbacks for MCS snooper and MFC update 3405 */ 3406void ecm_nss_multicast_ipv6_exit(void) 3407{ 3408 /* 3409 * De-register multicast update callbacks to 3410 * MFC and MCS snooper 3411 */ 3412 ip6mr_unregister_mfc_event_offload_callback(); 3413 mc_bridge_ipv6_update_callback_deregister(); 3414} 3415