| /* |
| * Copyright (c) 2009 Mindspeed Technologies, Inc. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License |
| * as published by the Free Software Foundation; either version 2 |
| * of the License, or (at your option) any later version. |
| |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| * |
| * |
| */ |
| |
| |
| #ifndef _MODULE_MC6_H_ |
| #define _MODULE_MC6_H_ |
| |
| #include "types.h" |
| #include "modules.h" |
| #include "channels.h" |
| #include "multicast.h" |
| #include "fe.h" |
| #include "module_ipv6.h" |
| |
| #define MC6_MAX_LISTENERS_PER_GROUP MCx_MAX_LISTENERS_PER_GROUP |
| |
| #define MC6_NUM_HASH_ENTRIES 16 |
| |
| typedef struct tMC6_context { |
| |
| unsigned char hoplimit_check_rule; |
| }MC6_context; |
| |
| #if defined (COMCERTO_2000) |
| |
| #if defined (COMCERTO_2000_CONTROL) |
| |
| /** Control path MC6 HW entry */ |
| typedef struct _thw_MC6Entry { |
| U32 flags; |
| U32 dma_addr; |
| U32 next; |
| U32 src_addr[4]; |
| U32 dst_addr[4]; |
| /* common portion */ |
| MCxEntry mcdest; |
| U16 status; |
| U8 rtpqos_slot; |
| U8 padding; // structure size must be a multiple of 8 bytes for EFET transfers |
| |
| /* These fields are only used by host software, so keep them at the end of the structure */ |
| struct dlist_head list; |
| struct _tMC6Entry *sw_entry; /**< pointer to the software flow entry */ |
| unsigned long removal_time; |
| }hw_MC6Entry, *Phw_MC6Entry; |
| |
| /** Control path MC6 SW entry */ |
| typedef struct _tMC6Entry { |
| struct slist_entry list; |
| U32 src_addr[4]; |
| U32 dst_addr[4]; |
| /* common portion */ |
| MCxEntry mcdest; |
| U16 status; |
| U8 padding[2]; //structure size must be a multiple of 8 bytes for EFET transfers |
| |
| hw_MC6Entry *hw_entry; |
| }MC6Entry, *PMC6Entry; |
| |
| |
| #else |
| /** Data path MC6 entry */ |
| typedef struct _tMC6Entry { |
| U32 flags; |
| U32 dma_addr; |
| U32 next; |
| U32 src_addr[4]; |
| U32 dst_addr[4]; |
| /* common portion */ |
| MCxEntry mcdest; |
| U16 status; |
| U8 rtpqos_slot; |
| U8 padding; //structure size must be a multiple of 8 bytes for EFET transfers |
| }MC6Entry, *PMC6Entry; |
| #endif |
| |
| #else /* COMCERTO 1000 */ |
| typedef struct _tMC6Entry { |
| struct slist_entry list; |
| U32 src_addr[4]; |
| U32 dst_addr[4]; |
| /* common portion */ |
| MCxEntry mcdest; |
| U16 status; |
| U8 rtpqos_slot; |
| U8 padding; //structure size must be a multiple of 8 bytes for EFET transfers |
| }MC6Entry, *PMC6Entry; |
| #endif |
| |
| |
| |
| /*********************************** |
| * MC4 API Command and Entry structures |
| * |
| ***********************************/ |
| typedef struct _tMC6Output { |
| U32 timer; |
| U8 output_device_str[11]; |
| U8 shaper_mask; |
| U8 uc_bit:1, |
| q_bit:1, |
| rsvd:6; |
| U8 uc_mac[6]; |
| U8 queue; |
| U8 new_output_device_str[11]; |
| U8 if_bit:1, |
| unused:7; |
| }MC6Output, *PMC6Output; |
| |
| typedef struct _tMC6Command { |
| U16 action; |
| U8 mode : 1, |
| queue : 5, |
| rsvd : 2; |
| U8 src_mask_len; |
| U32 src_addr[4]; |
| U32 dst_addr[4]; |
| U32 num_output; |
| MC6Output output_list[MCx_MAX_LISTENERS_IN_QUERY]; |
| }MC6Command, *PMC6Command; |
| #define MC6_MIN_COMMAND_SIZE 64 /* with one listener entry using 1 interface name */ |
| |
| |
| extern struct tMC6_context gMC6Ctx; |
| #if !defined(COMCERTO_2000) || defined(COMCERTO_2000_CONTROL) |
| extern struct slist_head mc6_table_memory[MC6_NUM_HASH_ENTRIES]; |
| #else |
| extern PVOID mc6_table_memory[MC6_NUM_HASH_ENTRIES]; |
| #endif |
| |
| BOOL mc6_init(void); |
| void mc6_exit(void); |
| void M_MC6_process_packet(PMetadata mtd) __attribute__((section ("fast_path"))); |
| #if !defined(COMCERTO_2000) |
| void M_mc6_entry(void) __attribute__((section ("fast_path"))); |
| #endif |
| |
| void MC6_interface_purge(U32 if_index); |
| |
| static inline u32 HASH_MC6(void *pdestaddr) // pass in ptr to IPv6 dest addr |
| { |
| u16 *p = (u16 *)pdestaddr; |
| u32 hash; |
| hash = ntohs(p[4]) + ntohs(p[5]) + ntohs(p[6]) + ntohs(p[7]); |
| hash = hash ^ (hash >> 4) ^ (hash >> 8) ^ (hash >> 12); |
| return hash & (MC6_NUM_HASH_ENTRIES - 1); |
| } |
| |
| #if defined(COMCERTO_2000_CLASS) |
| /** Searches multicast forwarding table for a match based on a given IPv6 header. |
| * @param[in] ipv6_hdr pointer to IPv6 header to be used for the search. |
| * @return pointer to matching entry, or NULL if no entry found. |
| */ |
| static __inline MC6Entry *MC6_rule_search_class(ipv6_hdr_t *ipv6_hdr) |
| { |
| PMC6Entry dmem_entry; |
| volatile PMC6Entry ddr_entry; |
| U32 *srca = ipv6_hdr->SourceAddress; |
| U32 *dsta = ipv6_hdr->DestinationAddress; |
| U32 hash_key; |
| |
| hash_key = HASH_MC6(dsta); |
| |
| ddr_entry = mc6_table_memory[hash_key]; |
| dmem_entry = (PVOID)(CLASS_ROUTE0_BASE_ADDR); |
| while (ddr_entry) { |
| efet_memcpy(dmem_entry, ddr_entry, sizeof(MC6Entry)); |
| while (dmem_entry->flags & HASH_ENTRY_UPDATING) |
| { |
| while (ddr_entry->flags & HASH_ENTRY_UPDATING) ; |
| efet_memcpy(dmem_entry, ddr_entry, sizeof(MC6Entry)); |
| } |
| |
| if (!IPV6_CMP(dsta, dmem_entry->dst_addr)) |
| { |
| if (ipv6_cmp_mask(srca, (U32*)dmem_entry->src_addr, dmem_entry->mcdest.src_mask_len)) { |
| return dmem_entry; |
| } |
| } |
| ddr_entry = (PMC6Entry) dmem_entry->next; |
| } |
| return NULL; |
| } |
| #else |
| /** Searches multicast forwarding table for match based on source and destination IPv6 addresses. |
| * @param[in] srca IPv6 source address |
| * @param[in] dsta IPv6 destination address |
| * @return pointer to matching entry, or NULL if no entry found. |
| */ |
| static __inline MC6Entry *MC6_rule_search(U32 *srca, U32 *dsta) |
| { |
| PMC6Entry this_entry; |
| struct slist_entry *entry; |
| U32 hash_key; |
| #define _l_src ((PACKED_U32 *)(srca)) |
| #define _l_dst ((PACKED_U32 *)(dsta)) |
| |
| hash_key = HASH_MC6(_l_dst); |
| slist_for_each(this_entry, entry, &mc6_table_memory[hash_key], list) |
| { |
| if (!IPV6_CMP(_l_dst,this_entry->dst_addr)) |
| { |
| if (ipv6_cmp_mask((U32*) _l_src, (U32*)this_entry->src_addr, this_entry->mcdest.src_mask_len)) { |
| return this_entry; |
| } |
| } |
| } |
| #undef _l_src |
| #undef _l_dst |
| return NULL; |
| } |
| #endif |
| |
| #endif /* _MODULE_MC6_H_ */ |