knet_rx.c (20605B)
1 #include <signal.h> 2 #include <inttypes.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <unistd.h> 6 #include <string.h> 7 #include <sys/socket.h> 8 #include <features.h> 9 #include <linux/if_packet.h> 10 #include <linux/if_ether.h> 11 #include <errno.h> 12 #include <sys/ioctl.h> 13 #include <net/if.h> 14 #include <net/ethernet.h> 15 #include <netinet/in.h> 16 #include <netinet/ether.h> 17 18 #define RCPU_SIGNATURE 0xB840 19 #define RX_MAX 9100 20 21 struct L2header { 22 uint8_t dest_mac[6]; 23 uint8_t src_mac[6]; 24 uint32_t tag; 25 uint16_t ether_type; 26 }; 27 28 struct RCPUheader { 29 uint16_t signature; 30 uint8_t opcode; 31 uint8_t flags; 32 uint16_t trans_id; 33 uint16_t data_len; 34 uint16_t reply_len; 35 uint32_t reserved; 36 }; 37 38 /* DEFINE for little endian processors */ 39 /* #define LE_HOST */ 40 41 /* 42 * DMA Control Block - Type 21 43 * Used on 56840 devices 44 * 16 words 45 */ 46 struct dcb21_s { 47 #ifdef REMOVE 48 uint32_t addr; /* T21.0: physical address */ 49 /* T21.1: Control 0 */ 50 #ifdef LE_HOST 51 uint32_t c_count:16, /* Requested byte count */ 52 c_chain:1, /* Chaining */ 53 c_sg:1, /* Scatter Gather */ 54 c_reload:1, /* Reload */ 55 c_hg:1, /* Higig (TX) */ 56 c_stat:1, /* Update stats (TX) */ 57 c_pause:1, /* Pause packet (TX) */ 58 c_purge:1, /* Purge packet (TX) */ 59 : 9; /* Don't care */ 60 #else 61 uint32_t:9, /* Don't care */ 62 c_purge:1, /* Purge packet (TX) */ 63 c_pause:1, /* Pause packet (TX) */ 64 c_stat:1, /* Update stats (TX) */ 65 c_hg:1, /* Higig (TX) */ 66 c_reload:1, /* Reload */ 67 c_sg:1, /* Scatter Gather */ 68 c_chain:1, /* Chaining */ 69 c_count:16; /* Requested byte count */ 70 #endif /* LE_HOST */ 71 #endif 72 uint32_t mh0; /* T21.2: Module Header word 0 */ 73 uint32_t mh1; /* T21.3: Module Header word 1 */ 74 uint32_t mh2; /* T21.4: Module Header word 2 */ 75 uint32_t mh3; /* T21.5: Module Header word 3 */ 76 #ifdef LE_HOST 77 /* T21.6 */ 78 uint32_t:3, /* Reserved */ 79 mtp_index:5, /* MTP index */ 80 cpu_cos:8, /* Queue number for CPU packets */ 81 inner_vid:12, /* Inner VLAN ID */ 82 inner_cfi:1, /* Inner Canoncial Format Indicator */ 83 inner_pri:3; /* Inner priority */ 84 85 /* T21.7 */ 86 uint32_t reason_hi:16, /* CPU opcode (high bits) */ 87 pkt_len:14, /* Packet length */ 88 : 2; /* Reserved */ 89 90 /* T21.8 */ 91 uint32_t reason; /* CPU opcode (low bits) */ 92 93 /* T21.9 */ 94 uint32_t dscp:6, /* New DSCP */ 95 : 2, /* Reserved */ 96 chg_tos:1, /* DSCP has been changed by HW */ 97 decap_tunnel_type:4, /* Tunnel type that was decapsulated */ 98 regen_crc:1, /* Packet modified and needs new CRC */ 99 : 2, /* Reserved */ 100 outer_vid:12, /* Outer VLAN ID */ 101 outer_cfi:1, /* Outer Canoncial Format Indicator */ 102 outer_pri:3; /* Outer priority */ 103 104 /* T21.10 */ 105 uint32_t timestamp; /* Timestamp */ 106 107 /* T21.11 */ 108 uint32_t:12, /* Reserved */ 109 ecn:2, /* New ECN value */ 110 chg_ecn:1, /* ECN changed */ 111 mcq:1, /* Multicast queue indicator */ 112 vfi:12, /* Internal VFI value */ 113 vfi_valid:1, /* Validates VFI field */ 114 dvp_nhi_sel:1, /* DVP overlay indicator */ 115 vntag_action:2; /* VN tag action */ 116 117 /* T21.12 */ 118 uint32_t srcport:8, /* Source port number */ 119 hgi:2, /* Higig Interface Format Indicator */ 120 itag_status:2, /* Ingress Inner tag status */ 121 otag_action:2, /* Ingress Outer tag action */ 122 itag_action:2, /* Ingress Inner tag action */ 123 service_tag:1, /* SD tag present */ 124 switch_pkt:1, /* Switched packet */ 125 hg_type:1, /* 0: Higig+, 1: Higig2 */ 126 src_hg:1, /* Source is Higig */ 127 l3routed:1, /* Any IP routed packet */ 128 l3only:1, /* L3 only IPMC packet */ 129 replicated:1, /* Replicated copy */ 130 : 2, /* Reserved */ 131 do_not_change_ttl:1, /* Do not change TTL */ 132 bpdu:1, /* BPDU Packet */ 133 : 5; /* Reserved */ 134 135 /* T21.13 */ 136 uint32_t uc_cos:4, /* COS value for unicast packet */ 137 eh_seg_sel:3, /* Extended Higig Seg Sel */ 138 next_pass_cp:2, /* Next pass code point */ 139 oam_pkt:1, /* OAM packet */ 140 : 2, /* Reserved */ 141 eh_tag_type:2, /* Extended Higig tag type */ 142 eh_tm:1, /* Extended Higig traffic mgr ctrl */ 143 eh_queue_tag:16,/* Extended Higig queue tag */ 144 hg2_ext_hdr:1; /* Extended Higig2 header valid */ 145 146 /* T21.14 */ 147 uint32_t l3_intf:14, /* L3 Intf num / Next hop idx */ 148 : 2, /* Reserved */ 149 match_rule:8, /* Matched FP rule */ 150 mc_cos2:4, /* COS2 value for multicast packets */ 151 mc_cos1:4; /* COS1 value for multicast packets */ 152 153 /* T21.15: DMA Status 0 */ 154 uint32_t count:16, /* Transferred byte count */ 155 end:1, /* End bit (RX) */ 156 start:1, /* Start bit (RX) */ 157 error:1, /* Cell Error (RX) */ 158 : 12, /* Reserved */ 159 done:1; /* Descriptor Done */ 160 #else 161 /* T21.6 */ 162 uint32_t inner_pri:3, /* Inner priority */ 163 inner_cfi:1, /* Inner Canoncial Format Indicator */ 164 inner_vid:12, /* Inner VLAN ID */ 165 cpu_cos:8, /* Queue number for CPU packets */ 166 mtp_index:5, /* MTP index */ 167 : 3; /* Reserved */ 168 169 /* T21.7 */ 170 uint32_t:2, /* Reserved */ 171 pkt_len:14, /* Packet length */ 172 reason_hi:16; /* CPU opcode (high bits) */ 173 174 /* T21.8 */ 175 uint32_t reason; /* CPU opcode (low bits) */ 176 177 /* T21.9 */ 178 uint32_t outer_pri:3, /* Outer priority */ 179 outer_cfi:1, /* Outer Canoncial Format Indicator */ 180 outer_vid:12, /* Outer VLAN ID */ 181 : 2, /* Reserved */ 182 regen_crc:1, /* Packet modified and needs new CRC */ 183 decap_tunnel_type:4, /* Tunnel type that was decapsulated */ 184 chg_tos:1, /* DSCP has been changed by HW */ 185 : 2, /* Reserved */ 186 dscp:6; /* New DSCP */ 187 188 /* T21.10 */ 189 uint32_t timestamp; /* Timestamp */ 190 191 /* T21.11 */ 192 uint32_t vntag_action:2, /* VN tag action */ 193 dvp_nhi_sel:1, /* DVP overlay indicator */ 194 vfi_valid:1, /* Validates VFI field */ 195 vfi:12, /* Internal VFI value */ 196 mcq:1, /* Multicast queue indicator */ 197 chg_ecn:1, /* ECN changed */ 198 ecn:2, /* New ECN value */ 199 : 12, /* Reserved */ 200 /* T21.12 */ 201 uint32_t:5, /* Reserved */ 202 bpdu:1, /* BPDU Packet */ 203 do_not_change_ttl:1, /* Do not change TTL */ 204 : 2, /* Reserved */ 205 replicated:1, /* Replicated copy */ 206 l3only:1, /* L3 only IPMC packet */ 207 l3routed:1, /* Any IP routed packet */ 208 src_hg:1, /* Source is Higig */ 209 hg_type:1, /* 0: Higig+, 1: Higig2 */ 210 switch_pkt:1, /* Switched packet */ 211 service_tag:1, /* SD tag present */ 212 itag_action:2, /* Ingress Inner tag action */ 213 otag_action:2, /* Ingress Outer tag action */ 214 itag_status:2, /* Ingress Inner tag status */ 215 hgi:2, /* Higig Interface Format Indicator */ 216 srcport:8; /* Source port number */ 217 218 /* T21.13 */ 219 uint32_t hg2_ext_hdr:1, /* Extended Higig2 header valid */ 220 eh_queue_tag:16,/* Extended Higig queue tag */ 221 eh_tm:1, /* Extended Higig traffic mgr ctrl */ 222 eh_tag_type:2, /* Extended Higig tag type */ 223 : 2, /* Reserved */ 224 oam_pkt:1, /* OAM packet */ 225 next_pass_cp:2, /* Next pass code point */ 226 eh_seg_sel:3, /* Extended Higig Seg Sel */ 227 uc_cos:4; /* COS value for unicast packet */ 228 229 /* T21.14 */ 230 uint32_t mc_cos1:4, /* COS1 value for multicast packets */ 231 mc_cos2:4, /* COS2 value for multicast packets */ 232 match_rule:8, /* Matched FP rule */ 233 : 2, /* Reserved */ 234 l3_intf:14; /* L3 Intf num / Next hop idx */ 235 236 /* T21.15: DMA Status 0 */ 237 uint32_t done:1, /* Descriptor Done */ 238 : 12, /* Reserved */ 239 error:1, /* Cell Error (RX) */ 240 start:1, /* Start bit (RX) */ 241 end:1, /* End bit (RX) */ 242 count:16; /* Transferred byte count */ 243 #endif 244 }; 245 246 static void 247 unpackL2header(unsigned char const *const pkt, struct L2header *header) 248 { 249 unsigned char const *vbuf; 250 int ix; 251 252 vbuf = &pkt[0]; 253 for (ix = 0; ix < 6; ix++) { 254 header->dest_mac[ix] = vbuf[ix]; 255 } 256 vbuf = &pkt[6]; 257 for (ix = 0; ix < 6; ix++) { 258 header->src_mac[ix] = vbuf[ix]; 259 } 260 vbuf = &pkt[12]; 261 header->tag = (vbuf[0] << 24) | (vbuf[1] << 16) | (vbuf[2] << 8) | vbuf[3]; 262 vbuf = &pkt[16]; 263 header->ether_type = (vbuf[0] << 8) | vbuf[1]; 264 } 265 266 static void 267 printL2header(unsigned char const *const pkt) 268 { 269 struct L2header header; 270 271 unpackL2header(pkt, &header); 272 printf("\nL2 header:\n"); 273 printf(" Dst MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 274 header.dest_mac[0], header.dest_mac[1], header.dest_mac[2], 275 header.dest_mac[3], header.dest_mac[4], header.dest_mac[5]); 276 printf(" Src MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", header.src_mac[0], 277 header.src_mac[1], header.src_mac[2], header.src_mac[3], header.src_mac[4], 278 header.src_mac[5]); 279 printf(" Tag: 0x%08x\n", header.tag); 280 printf(" EtherType: 0x%04x\n", header.ether_type); 281 } 282 283 static void 284 unpackRCPUheader(unsigned char const *const pkt, struct RCPUheader *header) 285 { 286 unsigned char const *vbuf; 287 288 vbuf = &pkt[18]; 289 290 header->signature = (vbuf[0] << 8) | vbuf[1]; 291 header->opcode = vbuf[2]; 292 header->flags = vbuf[3]; 293 header->trans_id = (vbuf[4] << 8) | vbuf[5]; 294 header->data_len = (vbuf[6] << 8) | vbuf[7]; 295 header->reply_len = (vbuf[8] << 8) | vbuf[9]; 296 header->reserved = (vbuf[10] << 24) | (vbuf[11] << 16) | (vbuf[12] << 8) | vbuf[13]; 297 } 298 299 static void 300 printRCPUheader(unsigned char const *const pkt) 301 { 302 struct RCPUheader header; 303 304 unpackRCPUheader(pkt, &header); 305 306 printf("\nRCPU Header:\n"); 307 printf(" Signature: 0x%04x; %s\n", header.signature, 308 (header.signature == RCPU_SIGNATURE) ? "OK" : "INVALID"); 309 printf(" Opcode: 0x%02x\n", header.opcode); 310 printf(" Flags: 0x%02x\n", header.flags); 311 printf(" Trans ID: 0x%04x\n", header.trans_id); 312 printf(" Data len: %d\n", header.data_len); 313 printf(" Reply len: %d\n", header.reply_len); 314 printf(" Reserved: 0x%08x\n", header.reserved); 315 } 316 317 static void 318 printMetaData(unsigned char *pkt) 319 { 320 uint32_t *wbuf; 321 int ix; 322 struct dcb21_s *dcbHack; 323 324 /* 325 * The Rx meta data is essentially the architecture specific DCB. 326 * We skip the first 8 bytes since that information isn't very useful. 327 * This means the metadata for may differ from one device type to another. 328 */ 329 330 printf("\nRCPU Meta Data:\n"); 331 wbuf = (uint32_t *) & pkt[0]; 332 #if 0 333 dcbHack = (struct dcb21_s *) &pkt[32]; 334 printf("DCB: Packet Len: %d;\n", dcbHack->pkt_len); 335 printf("DCB: Reason Hi: %X; Low: %X\n", dcbHack->reason_hi, dcbHack->reason); 336 printf("DCB: Outer VLAN: %d; Outer CFI: %d; Outer Priority: %d\n", 337 dcbHack->outer_vid, dcbHack->outer_cfi, dcbHack->outer_pri); 338 printf("DCB: BPDU Packet: %d\n", dcbHack->bpdu); 339 printf("DCB: Do not change TTL: %d\n", dcbHack->do_not_change_ttl); 340 printf("DCB: Replicated copy: %d\n", dcbHack->replicated); 341 printf("DCB: L3 only IPMC packet: %d\n", dcbHack->l3only); 342 printf("DCB: Any IP routed packet: %d\n", dcbHack->l3routed); 343 printf("DCB: Source is Higig: %d\n", dcbHack->src_hg); 344 printf("DCB: 0: Higig+, 1: Higig2: %d\n", dcbHack->hg_type); 345 printf("DCB: Switched packet: %d\n", dcbHack->switch_pkt); 346 printf("DCB: SD tag present: %d\n", dcbHack->service_tag); 347 printf("DCB: Ingress Inner tag action: %d\n", dcbHack->itag_action); 348 printf("DCB: Ingress Outer tag action: %d\n", dcbHack->otag_action); 349 printf("DCB: Ingress Inner tag status: %d\n", dcbHack->itag_status); 350 printf("DCB: Higig Interface Format Indicator: %d\n", dcbHack->hgi); 351 printf("DCB: Source port number: %d\n", dcbHack->srcport); 352 #endif 353 354 for (ix = 0; ix < 16; ix++) { 355 if ((ix & 1) == 0) { 356 printf(" Word %2d: 0x%08X", ix, wbuf[ix]); 357 } else { 358 printf("; 0x%08X\n", wbuf[ix]); 359 } 360 } 361 } 362 363 static void 364 dump_raw(uint8_t * rx_packet, int rx_len) 365 { 366 int ix; 367 368 printf("\nRaw Packet Dump (%d bytes):\n", rx_len); 369 for (ix = 0; ix < rx_len; ix++) { 370 if ((ix & 0xf) == 0) { 371 printf("0x%04x:", ix); 372 } else if ((ix & 0xf) == 8) { 373 printf(" -"); 374 } 375 printf(" 0x%02x", rx_packet[ix]); 376 if ((ix & 0xf) == 0xf) { 377 printf("\n"); 378 } 379 } 380 if ((ix & 0xf) != 0) { 381 printf("\n"); 382 } 383 } 384 385 static int 386 create_raw_socket(int protocol_to_sniff) 387 { 388 int rawsock; 389 390 if ((rawsock = socket(PF_PACKET, SOCK_RAW, htons(protocol_to_sniff))) < 0) { 391 perror("Error creating raw socket: "); 392 return rawsock; 393 } 394 395 return rawsock; 396 } 397 398 static int 399 bind_raw_socket(char *device, int rawsock, int protocol) 400 { 401 402 struct sockaddr_ll sll; 403 struct ifreq ifr; 404 405 bzero(&sll, sizeof(sll)); 406 bzero(&ifr, sizeof(ifr)); 407 408 /* First Get the Interface Index */ 409 strncpy((char *) ifr.ifr_name, device, IFNAMSIZ); 410 if ((ioctl(rawsock, SIOCGIFINDEX, &ifr)) == -1) { 411 printf("Error getting interface index for %s\n", device); 412 return -1; 413 } 414 415 /* Bind our raw socket to this interface */ 416 sll.sll_family = AF_PACKET; 417 sll.sll_ifindex = ifr.ifr_ifindex; 418 sll.sll_protocol = htons(protocol); 419 420 if ((bind(rawsock, (struct sockaddr *) &sll, sizeof(sll))) == -1) { 421 perror("Error binding raw socket to interface\n"); 422 return -1; 423 } 424 425 return 0; 426 } 427 428 void 429 dump_rcpu_encap(unsigned char *pkt) 430 { 431 printL2header(pkt); 432 printRCPUheader(pkt); 433 printMetaData(pkt); 434 } 435 436 static int rawsock = -1; 437 static int rx_packets = 0; 438 static char *ifname = NULL; 439 440 static void 441 sigint(int signum) 442 { 443 /*Clean up....... */ 444 445 struct ifreq ifr; 446 447 if ((rawsock == -1) || (ifname == NULL)) { 448 return; 449 } 450 451 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 452 ioctl(rawsock, SIOCGIFFLAGS, &ifr); 453 ifr.ifr_flags &= ~IFF_PROMISC; 454 ioctl(rawsock, SIOCSIFFLAGS, &ifr); 455 close(rawsock); 456 457 printf("RX terminating ...\n"); 458 459 printf("Total packets received: %d\n", rx_packets); 460 exit(0); 461 } 462 463 static void 464 usage(const char *const prog) 465 { 466 printf("Usage %s [-v] [-vv] interface [maxRxPackets]\n", prog); 467 printf("-r ; RCPU mode\n"); 468 printf("-v ; Be verbose\n"); 469 printf("-vv ; Be very verbose\n"); 470 printf("interface ; ethernet interface (eth5)\n"); 471 printf("maxRxPackets ; Exit after receiving this many packets\n"); 472 } 473 474 int 475 main(int argc, char **argv) 476 { 477 int rcpu = 0; 478 int ax; 479 int max_packets = -1; 480 int rx_len; 481 int verbose = 0; 482 int vverbose = 0; 483 socklen_t len; 484 struct sockaddr_ll skaddr; 485 uint8_t rx_packet[RX_MAX]; 486 487 for (ax = 1; ax < argc; ax++) { 488 if (argv[ax][0] == '-') { 489 char *flag = &argv[ax][1]; 490 491 if (strcmp(flag, "v") == 0) { 492 verbose = 1; 493 } else if (strcmp(flag, "vv") == 0) { 494 verbose = 1; 495 vverbose = 1; 496 } else if (strcmp(flag, "r") == 0) { 497 rcpu = 1; 498 } else { 499 fprintf(stderr, "ERROR: unknown switch %s\n", argv[ax]); 500 usage(argv[0]); 501 return -2; 502 } 503 } else { 504 if (ifname == NULL) { 505 ifname = argv[ax]; 506 } else if (max_packets < 0) { 507 max_packets = atoi(argv[ax]); 508 if (max_packets == 0) { 509 printf("Bogus packet count\n"); 510 return -2; 511 } 512 } else { 513 fprintf(stderr, "ERROR: unknown argument %s\n", argv[ax]); 514 usage(argv[0]); 515 return -2; 516 } 517 } 518 } 519 520 if (ifname == NULL) { 521 usage(argv[0]); 522 return -1; 523 } 524 525 /*establish signal handler */ 526 if (SIG_ERR == signal(SIGINT, sigint)) { 527 return 2; 528 } 529 530 if (max_packets <= 0) { 531 max_packets = 1000000; 532 } 533 534 /* Create the raw socket */ 535 rawsock = create_raw_socket(ETH_P_ALL); 536 537 if (rawsock < 0) { 538 return 1; 539 } 540 541 /* Bind raw socket to interface */ 542 if (bind_raw_socket(ifname, rawsock, ETH_P_ALL) < 0) { 543 return 2; 544 } 545 546 rx_packets = 0; 547 while (rx_packets < max_packets) { 548 549 if (vverbose) { 550 printf("\nWaiting on packet %d\n", rx_packets + 1); 551 } 552 553 memset(&skaddr, 0, sizeof(skaddr)); 554 skaddr.sll_protocol = htons(ETH_P_ALL); 555 len = sizeof(struct sockaddr); 556 557 if ((rx_len = recvfrom(rawsock, rx_packet, RX_MAX, 0, 558 (struct sockaddr *) &skaddr, &len)) > 0) { 559 int packet_type = ntohs(skaddr.sll_pkttype); 560 561 if (skaddr.sll_pkttype == PACKET_OUTGOING) { 562 if (vverbose) { 563 printf("Skipping %d byte outgoing packet;\n", rx_len); 564 } 565 continue; 566 } 567 rx_packets++; 568 if (verbose) { 569 printf 570 ("\n--------------------------------------------------------------------------------\n"); 571 } 572 if (verbose) { 573 printf("Received packet %d (%d bytes)\n", rx_packets, rx_len); 574 #if 0 575 if (vverbose) { 576 static const char *packet_types[] = 577 { "HOST", "BROADCAST", "MULTICAST", "OTHERHOST", "OUTGOING", 578 "LOOPBACK", "FASTROUTE" 579 }; 580 printf(" Interface Index = %d; Packet Type = %s\n", 581 skaddr.sll_ifindex, packet_types[packet_type]); 582 } 583 #endif 584 if (rcpu) { 585 dump_rcpu_encap(rx_packet); 586 } else { 587 printf("Dump L2 Header\n"); 588 printL2header(rx_packet); 589 } 590 if (vverbose) { 591 printf("Dump Raw Packet\n"); 592 dump_raw(rx_packet, rx_len); 593 } 594 } else { 595 if ((rx_packets & 0x1FFF) == 0) { 596 printf("Rx Packet Count: %8d\n", rx_packets); 597 } 598 } 599 } 600 if (rx_len < 0) { 601 perror("recvfrom()"); 602 } 603 } 604 printf("Received %d packets, DONE\n", max_packets); 605 606 close(rawsock); 607 608 return 0; 609 } 610