📄 entest.c
字号:
This function sends out a SIF packet out on the interface. It initializes the destination address before doing so.*****************************************************************************/void send_sif_packet (addr)mac_addr_t* addr;{ struct sockaddr sock_addr; struct strbuf data, ctl; machdr_t* machdr; func_name = "send_sif_packet"; TRACE_IN /* * Initialize the stream buffer structures for send/recv calls */ ctl.len = sizeof (struct sockaddr); data.len = sizeof (smthdr_t); ctl.buf = (char*) &sock_addr; data.buf = (char*) &sif; /* * Initialize the fields of the structure sock_addr. */ sock_addr.sa_family = AF_UNSPEC; machdr = (machdr_t*) sock_addr.sa_data; memcpy (machdr->da.octet, (char*) addr, sizeof (mac_addr_t)); memcpy (machdr->sa.octet, our_addr.octet, sizeof (mac_addr_t)); machdr->type = MAC_FC; if (putmsg (fd, &ctl, &data, 0) < 0) { send_message (-SEND_FAIL, FATAL, "%s could not send: %s", test_name, errmsg (errno)); } send_message (0, VERBOSE, "%s Sent the SIF packet successfully", test_name); TRACE_OUT}/***************************************************************************** cmp_fddi_addr (addr1, addr2) This function compares the address' addr1 and addr2. The address 'addr1' is in the normal form and the address 'addr2' is in the FDDI format with the most significant bit in bit 0 and the least significant bit in bit 7. This function returns a non-zero value on miscompare.*****************************************************************************/int cmp_fddi_addr (addr1, addr2)u_char* addr1;u_char* addr2;{ int status = 0; u_char j; u_char i = 0; u_char tmp; func_name = "cmp_fddi_addr"; TRACE_IN while ((!status) && (i < 6)) { tmp = 0; for (j = 1 ; j != 0; j <<= 1) { /* format the FDDI addr */ if (j & *(addr2 + i)) { tmp += 128 / j; } } if (tmp != *(addr1 + i)) { status = 1; } i++; } TRACE_OUT return (status);} /***************************************************************************** receive_sif_packet () This function reads the stream. The global buffers 'recv_cntl' and 'recv_data' will hold the packet on return. The function 'getmsg' is used to read the stream head. We wait a maximum of 30 seconds for a successful read from the stream. If after the 30 seconds there is no message at the stream head we exit the program.*****************************************************************************/void receive_sif_packet (){ int mode = 0; int done = 0; int i = 30; /* 30 seconds */ struct strbuf l_cntl; struct strbuf l_data; func_name = "receive_sif_packet"; TRACE_IN l_cntl.len = l_data.len = 0; l_cntl.maxlen = l_data.maxlen = BUFSIZ; l_cntl.buf = (char*) recv_cntl; l_data.buf = (char*) recv_data; while ((!done) && (i > 0)) { switch (getmsg (fd, &l_cntl, &l_data, &mode)) { case EAGAIN: send_message (0, DEBUG, "%s stream empty: %s", test_name, errmsg (errno)); i--; sleep (1); /* wait for a second */ break; case 0: done = 1; send_message (0, VERBOSE, "%s Received the SIF packet successfully", test_name); break; default: send_message (-RECV_FAIL, FATAL, "%s couldn't receive: %s", test_name, errmsg (errno)); break; } } if (!i) { send_message (-RECV_TMOUT, FATAL, "%s getmsg timed out", test_name); } TRACE_OUT}/***************************************************************************** get_neighbor_address () This function finds out the Upstream and Downstream neighbor addresses of this node. Then it examines each packets MAC field to determine if it is our immediate Upstream or Downstream neighbor. When this function returns the global variables 'una' and 'dna' contain valid addresses of the Upstream and Downstream neighbor respectively. - Send out a SIF Configuration Request to everybody by broadcasting - Read the stream untill we find out the Upstream/Downstream neighbors NOTE: The SIF Response packet information field varies from revision to revision. This may affect where exactly you will find the Up/Down stream neighbor address. The testing for the neighbor address should be modifed as the version specifies.*****************************************************************************/void get_neighbor_address (){ int done = 0; u_short index = 0; u_short param_type = 0; sif_resp_t* sif_resp; func_name = "get_neighbor_address"; TRACE_IN send_sif_packet (&broadcast); sif_resp = (sif_resp_t*) recv_data; while (done != 2) /* until UNA & DNA are found */ { param_type = 0; receive_sif_packet (); /* * Check that we have the right kind of frame. The packet * filter just checks to see that we have a SMT frame. We * check in the following order: * * - frame class should be SIF * - frame type should be an response * - transaction id should match with our own copy * * If this condition is satisfied then we check the MAC * neighbor field of the packets info field. If the upstream * or the downstream neighbors address match our address then * we have a neighbor! Save the source address appropriately */ if ((sif_resp->smt.frame_class == SMT_SIF_CLASS) && (sif_resp->smt.frame_type == SMT_SIF_RESPONSE) && (sif_resp->smt.transaction_id == 0x12345678)) { /* * Figure out the index for the MAC Neighbors field in the * information field */ while ((param_type = * (u_short*) &sif_resp->sif_info_field[index]) != MAC_NEIGHBOR) { index += * (u_short*) &sif_resp->sif_info_field[index + 2] + 4; } if (!cmp_fddi_addr (our_addr.octet, &sif_resp->sif_info_field[index + 8])) { memcpy (dna.octet, &sif_resp->machdr.sa, sizeof (mac_addr_t)); send_message (0, VERBOSE, "%s DNA: %d:%d:%d:%d:%d:%d", test_name, dna.octet[0], dna.octet[1], dna.octet[2], dna.octet[3], dna.octet[4], dna.octet[5]); done++; } if (!cmp_fddi_addr (our_addr.octet, &sif_resp->sif_info_field[index + 14])) { memcpy (una.octet, &sif_resp->machdr.sa, sizeof (mac_addr_t)); send_message (0, VERBOSE, "%s UNA: %d:%d:%d:%d:%d:%d", test_name, una.octet[0], una.octet[1], una.octet[2], una.octet[3], una.octet[4], una.octet[5]); done++; } } } TRACE_OUT}/***************************************************************************** run_fddi_tests (num_passes) This function runs the actual test until 'num_passes' number of passes are registered. If we hit the error threshold as specified in ERROR_LIMIT then the function is exited also. This function returns the number of errors encountered during the test.*****************************************************************************/int run_fddi_tests (num_passes){ int l_passes = 0; int l_errors = 0; int i = 0; int done = 0; sif_resp_t* sif_resp; mac_addr_t dest; func_name = "run_fddi_tests"; TRACE_IN /* * arbitrary, but different from the broadcast SIF packet which is * 0x12345678 */ sif.transaction_id = 0x87654321; /* * Talk a while with the Upstream Neighbor untill we are bored */ sif_resp = (sif_resp_t*) recv_data; while ((l_passes < (num_passes * 2)) && (!done)) { send_message (0, VERBOSE, "%s Loop #: %d", test_name, l_passes); if (i++ % 2) { send_message (0, VERBOSE, "Talking to Upstream Neighbor"); memcpy (dest.octet, una.octet, sizeof (mac_addr_t)); } else { send_message (0, VERBOSE, "Talking to Downstream Neighbor"); memcpy (dest.octet, dna.octet, sizeof (mac_addr_t)); } send_sif_packet (&dest); receive_sif_packet (); if ((sif_resp->smt.frame_class == SMT_SIF_CLASS) && (sif_resp->smt.frame_type == SMT_SIF_RESPONSE) && (sif_resp->smt.transaction_id == 0x87654321)) { if (memcmp(&sif_resp->machdr.sa, &dest, sizeof (mac_addr_t)) == 0) { l_passes++; } else { done++; send_message (-SA_MISMATCH, ERROR, "Bad SA in SIF response"); if (++l_errors >= ERROR_LIMIT) { send_message (-TOOMANY_ERR, ERROR, "Too many errors"); TRACE_OUT return (l_errors); } else { if (!run_on_error) { send_message (-EXIT_ON_ERROR, ERROR, "Exiting on first error"); TRACE_OUT return (1); } } } } } TRACE_OUT return (l_errors);}/***************************************************************************** clean_up () This function is called before exiting program in any way. This function closes all the open file descriptors, programs the FDDI firmware to its default state.*****************************************************************************/clean_up(){ func_name = "clean_up"; close (fd); /* close /dev/nit */ if (fw_reconfigured == RECONFIGURED) { fddi_fw_setup (ENABLE); }}/***************************************************************************** fddi_test *****************************************************************************/voidfddi_test(){ func_name = "fddi_test"; /* * Initialize all the necessary stuff like the test name, parse * the command line.... */ TRACE_IN versionid = "1.1"; device_name = DEVICE_NAME; /* * If we are running from within SunDiag, then no need to do * verify that the interface is present. Because SunDiag will not * allow the user to call the test if the interface is not present. */ if (!exec_by_sundiag) {/* test_init (argc, argv, NULL, NULL, NULL);*/ fddi_probe (); } /* * Set up the FDDI board to respond and pass up all SMT frames. * This is required to run this test. We send out SIF frames, * which belong to the broad class of SMT frames, during the * course of test to establish the upstream and downstream * neighbor addresses and communicate with them. This involves * setting a bit in the FDDI firmware. */ fddi_fw_setup (DISABLE); fw_reconfigured = RECONFIGURED; /* * Open a streams interface to the FDDI */ fd = nit_open (); /* * Initialize the different fields of a SIF Configuration Request packet. */ init_sif_packet (); /* * Build neighbor addresses by sending out a SIF configuration request * packet. */ get_neighbor_address (); /* * The function run_fddi_tests actually executes the test. If the * variable 'single_pass' dictates how long the test will take. */ run_fddi_tests ((single_pass || quick_test) ? 1 : TOTAL_PASS); /* * Reset the FDDI firmware to its default state. */ fddi_fw_setup (ENABLE); TRACE_OUT}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -