knet.c (10732B)
1 /* Feature : KNET 2 * 3 * Usage : BCM.0> cint knet.c 4 * 5 * config : knet_config.bcm 6 * 7 * Log file : knet_log.txt 8 * 9 * Test Topology : 10 * 11 * +------------------------------+ 12 * | | 13 * | | 14 * | | 15 * | | 16 * +----------------+ SWITCH +-----------------+ 17 * | | 18 * | | 19 * | | 20 * | | 21 * | | 22 * +------------------------------+ 23 * 24 * 25 * Summary: 26 * ======== 27 * This CINT script demonstrate how to send and receive packets over KNET interface 28 * This exampls shows how application can create KNET interface 29 * and send/receive packets over it. 30 * 31 * Prerequistes: 32 * ============= 33 * a) Build SDK with KNET feature enabled 34 * b) Build $SDK/src/examples/xgs/tomahawk3/knet/knet_tx.c and knet_rx.c 35 * source files for customer target CPU 36 * c) Insert knet kernel module before launching SDK. 37 * 38 * Detailed steps done in the CINT script: 39 * ===================================================== 40 * 1) Step1 - Test Setup (Done in test_setup()) 41 * ============================================ 42 * a) Enable siwtch control "ArpReplyToCpu" and "ArpRequestCpu" 43 * b) Enable BCM RX module and register Rx Callback 44 * c) Add IFP rules to copy protocol and data packets to CPU 45 * 46 * 2) Step2 - Configuration (Done in knet_setup()) 47 * =============================================== 48 * a) Create Knet interface of type BCM_KNET_NETIF_T_TX_CPU_INGRESS 49 * b) Create Knet filter to divert packets to Knet interface 50 * 51 * 3) Step3 - Verification (Done in verify()) 52 * =========================================== 53 * a) Provided steps to user for sending and receiving packets 54 * through knet interface 55 * b) Expected Result: 56 * ================ 57 * knet_tx executable will send 5 packets over knet interface 58 * knet_rx executable will receive 5 packets over knet interface and display 59 */ 60 61 cint_reset(); 62 63 bcm_error_t 64 knet_setup(int unit) 65 { 66 bcm_error_t rv = BCM_E_NONE; 67 const bcm_mac_t local_mac = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE }; 68 const char *device_name = "virt-intf0"; 69 70 printf("Create a KNET interface to handle protocol and local station packets\n"); 71 rv = create_knet_interface(unit, device_name, local_mac); 72 if(BCM_FAILURE(rv)) { 73 printf("\nError in create_knet_interface() : %s\n", bcm_errmsg(rv)); 74 return rv; 75 } 76 77 printf("DONE; don't forget \"ifconfig virt-intf 192.168.2.254 netmask 255.255.255.0 up\"\n"); 78 return rv; 79 } 80 81 /* 82 * Create a KNET interface with two filters to direct protocol and filter match 83 * IP packets to it. 84 */ 85 bcm_error_t 86 create_knet_interface(int unit, char *device_name, bcm_mac_t local_mac) 87 { 88 bcm_error_t rv = BCM_E_NONE; 89 bcm_knet_filter_t filter1; 90 bcm_knet_filter_t filter2; 91 bcm_knet_netif_t netif; 92 int count; 93 94 /* Send packets through ingress logic */ 95 netif.type = BCM_KNET_NETIF_T_TX_CPU_INGRESS; 96 netif.vlan = 2; 97 netif.port = 0 ; 98 netif.flags = 0 ; 99 sal_strcpy(netif.name, device_name); /* Set device name */ 100 /* Set MAC address associated with this interface */ 101 netif.mac_addr = local_mac; 102 103 printf("bcm_knet_netif_create\n"); 104 rv = bcm_knet_netif_create(unit, &netif); 105 if(BCM_FAILURE(rv)) { 106 printf("\nError in bcm_knet_netif_create() : %s\n", bcm_errmsg(rv)); 107 return rv; 108 } 109 110 /* Add filter to catch protocol packets */ 111 sal_strcpy(filter1.desc, "Protocol Packets"); 112 filter1.type = BCM_KNET_FILTER_T_RX_PKT; 113 filter1.flags = BCM_KNET_FILTER_F_STRIP_TAG; 114 filter1.priority = 50; 115 /* Send packet to network interface */ 116 filter1.dest_type = BCM_KNET_DEST_T_NETIF; 117 filter1.dest_id = netif.id; 118 filter1.match_flags = BCM_KNET_FILTER_M_REASON; 119 BCM_RX_REASON_SET(&filter1.m_reason, bcmRxReasonProtocol); 120 printf("bcm_knet_filter_create 1\n"); 121 rv = bcm_knet_filter_create(unit, &filter1); 122 if(BCM_FAILURE(rv)) { 123 printf("\nError in bcm_knet_filter_create() : %s\n", bcm_errmsg(rv)); 124 return rv; 125 } 126 127 /* Add filter to catch nexthop packets */ 128 sal_strcpy(filter2.desc, "Filter Match Packets"); 129 filter2.type = BCM_KNET_FILTER_T_RX_PKT; 130 filter2.flags = BCM_KNET_FILTER_F_STRIP_TAG; 131 filter2.priority = 55; 132 filter2.dest_type = BCM_KNET_DEST_T_NETIF; 133 filter2.dest_id = netif.id; 134 filter2.match_flags = BCM_KNET_FILTER_M_REASON; 135 BCM_RX_REASON_SET(&filter2.m_reason, bcmRxReasonFilterMatch); 136 printf("bcm_knet_filter_create 2\n"); 137 rv = bcm_knet_filter_create(unit, &filter2); 138 if(BCM_FAILURE(rv)) { 139 printf("\nError in bcm_knet_filter_create() : %s\n", bcm_errmsg(rv)); 140 return rv; 141 } 142 return rv; 143 } 144 145 bcm_error_t 146 configure_ifp (int unit) 147 { 148 bcm_error_t rv = BCM_E_NONE; 149 150 bcm_field_group_config_t group_config; 151 bcm_field_entry_t eid; 152 bcm_vlan_t vlan = 2, vlan_mask = 0xfff; 153 bcm_port_t port = 0, port_mask = 0xffffffff; 154 int prio; 155 156 /* Enable IFP for CPU port */ 157 rv = bcm_port_control_set(unit, port, bcmPortControlFilterIngress, 1); 158 159 /* FP group configuration and creation */ 160 bcm_field_group_config_t_init(&group_config); 161 162 BCM_FIELD_QSET_INIT(group_config.qset); 163 BCM_FIELD_QSET_ADD(group_config.qset, bcmFieldQualifyStageIngress); 164 BCM_FIELD_QSET_ADD(group_config.qset, bcmFieldQualifyInPort); 165 166 group_config.mode = bcmFieldGroupModeAuto; 167 168 rv = bcm_field_group_config_create(unit, &group_config); 169 if(BCM_FAILURE(rv)) { 170 printf("\nError in bcm_field_group_config_create() : %s\n", bcm_errmsg(rv)); 171 return rv; 172 } 173 174 /* FP entry configuration and creation */ 175 rv = bcm_field_entry_create(unit, group_config.group, &eid); 176 if(BCM_FAILURE(rv)) { 177 printf("\nError in bcm_field_entry_create() : %s\n", bcm_errmsg(rv)); 178 return rv; 179 } 180 181 rv = bcm_field_qualify_InPort(unit, eid, port, port_mask); 182 if(BCM_FAILURE(rv)) { 183 printf("\nError in bcm_field_qualify_InPort() : %s\n", bcm_errmsg(rv)); 184 return rv; 185 } 186 187 /* FP entry actions configuration */ 188 rv = bcm_field_action_add(unit, eid, bcmFieldActionDrop, 0, 0); 189 if(BCM_FAILURE(rv)) { 190 printf("\nError in bcm_field_action_add() : %s\n", bcm_errmsg(rv)); 191 return rv; 192 } 193 194 rv = bcm_field_action_add(unit, eid, bcmFieldActionCopyToCpu, 0, 0); 195 if(BCM_FAILURE(rv)) { 196 printf("\nError in bcm_field_action_add() : %s\n", bcm_errmsg(rv)); 197 return rv; 198 } 199 200 /* Installing FP entry to FP TCAM */ 201 rv = bcm_field_entry_install(unit, eid); 202 if(BCM_FAILURE(rv)) { 203 printf("\nError in bcm_field_entry_install() : %s\n", bcm_errmsg(rv)); 204 return rv; 205 } 206 207 return rv; 208 } 209 210 /* Receive Task Callback 211 * 212 * This routine catches bcm_rx packets and prints a simple message. 213 */ 214 bcm_rx_t 215 packetWatcher(int unit, bcm_pkt_t * pkt, void *cookie) 216 { 217 int *count = (auto) cookie; 218 219 (*count)++; 220 printf("Packet: %3d; Size: %d; Src Port: %d; VLAN: %d;", *count, 221 pkt->pkt_len, pkt->src_port, pkt->vlan); 222 if (BCM_RX_REASON_IS_NULL(pkt->rx_reasons)) { 223 printf(" Switched to CPU\n"); 224 } else { 225 printf(" Sent for Reason\n"); 226 } 227 return BCM_RX_HANDLED; 228 } 229 230 int packet_count = 0; 231 232 bcm_error_t 233 rx_init(int unit) 234 { 235 bcm_error_t rv = BCM_E_NONE; 236 const int priority = 101; 237 const int flags = BCM_RCO_F_ALL_COS; 238 239 if (!bcm_rx_active(unit)) { 240 rv = bcm_rx_init(unit); 241 if(BCM_FAILURE(rv)) { 242 printf("\nError in bcm_rx_init() : %s\n", bcm_errmsg(rv)); 243 return rv; 244 } 245 rv = bcm_rx_start(unit, NULL); 246 if(BCM_FAILURE(rv)) { 247 printf("\nError in bcm_rx_start() : %s\n", bcm_errmsg(rv)); 248 return rv; 249 } 250 251 } 252 253 rv = bcm_rx_register(unit, "Rx PacketWatch", 254 packetWatcher, priority, &packet_count, 255 flags); 256 if(BCM_FAILURE(rv)) { 257 printf("\nError in bcm_rx_register() : %s\n", bcm_errmsg(rv)); 258 return rv; 259 } 260 261 return rv; 262 } 263 264 265 bcm_error_t 266 test_setup(int unit) 267 { 268 bcm_error_t rv = BCM_E_NONE; 269 270 rv = bcm_switch_control_set(unit, bcmSwitchArpReplyToCpu, TRUE); 271 if(BCM_FAILURE(rv)) { 272 printf("\nError in bcm_switch_control_set() 273 bcmSwitchArpReplyToCpu : %s.\n",bcm_errmsg(rv)); 274 return rv; 275 } 276 277 rv = bcm_switch_control_set(unit, bcmSwitchArpRequestToCpu, TRUE); 278 if(BCM_FAILURE(rv)) { 279 printf("\nError in bcm_switch_control_set() 280 bcmSwitchArpRequestToCpu : %s.\n",bcm_errmsg(rv)); 281 return rv; 282 } 283 284 rv = rx_init(unit); 285 if(BCM_FAILURE(rv)) { 286 printf("\nError in rx_init(): %s.\n",bcm_errmsg(rv)); 287 return rv; 288 } 289 290 rv = configure_ifp(unit); 291 if(BCM_FAILURE(rv)) { 292 printf("\nError in configure_ifp(): %s.\n",bcm_errmsg(rv)); 293 return rv; 294 } 295 296 return rv; 297 } 298 299 void verify(int unit) 300 { 301 printf("\nUser has to follow below steps to verify KNET functionality\n"); 302 printf("====================================================================================\n"); 303 printf("1. Go to Linux shell prompt using \"shell\" command from BCM diag shell\n"); 304 printf("2. Configure IP address to knet interface \"ifconfig virt-intf 192.168.2.254 netmask 255.255.255.0 up\" \n"); 305 printf("3. Run knet_rx.exe in backround \"./knet_rx.exe -vv virt-intf0 5 &\"\n"); 306 printf("4. Run knet_tx.exe to send 5 packets \"./knet_tx.exe -vv virt-intf0 5\" \n"); 307 printf("=====================================================================================\n"); 308 printf("Above 4 steps will demonstrate transmit and receive functionality over KNET interface\n"); 309 310 } 311 312 bcm_error_t execute() 313 { 314 bcm_error_t rv; 315 int unit =0; 316 bshell(unit, "config show; a ; version"); 317 if (BCM_FAILURE((rv = test_setup(unit)))) { 318 printf("test_setup() failed.\n"); 319 return -1; 320 } 321 322 if (BCM_FAILURE((rv = knet_setup(unit)))) { 323 printf("KNET Setup Failed\n"); 324 return -1; 325 } 326 327 verify(unit); 328 return BCM_E_NONE; 329 } 330 331 const char *auto_execute = (ARGC == 1) ? ARGV[0] : "YES"; 332 if (!sal_strcmp(auto_execute, "YES")) { 333 print execute(); 334 }