int main(void) { uint8_t data; watchdog_stop(); set_mcu_speed_dco_mclk_16MHz_smclk_8MHz(); led_red_on(); uart_init(UART_9600_SMCLK_8MHZ); serial_ring_init(); uart_register_cb( serial_cb); printf("serial test application: echo\n"); led_green_on(); eint(); for(;;) { LPM(1); if (serial_ring_get(&data)) { putchar(data); led_green_switch(); } else { printf("\n\n serial_ring_get() returns 0 : empty ring\n\n"); led_red_switch(); } } }
/* This will foreward the given IP packet It checks for the Destination IP address and finds appropriate interface (LPM) and sends out! */ int forward_packet(struct sr_instance* sr,uint8_t* packet,int len,int packet_src_iface) { uint32_t ip; sr_ip_hdr_t* ip_header = (sr_ip_hdr_t*)packet; /* Get Dest IP */ ip = ip_header->ip_dst; /* This target variable stores the next hop */ struct sr_rt* target = NULL; /* Perform LPM and get the target routing table entry which has the interface to pass and next hop IP */ target = LPM(sr->routing_table,ip); /* Now the next hop ip (dest->gw) is known and the interface also */ if( target == NULL ) { /* ICMP Destination Unreachable */ /* There is no routing table entry for this destination IP address Now we have to send this packet encapsulated in ICMP packet with 3,0( Destiantion Network Unreachable ) with src address of the incoming interface address and destination address as the source */ /* We have IP packet, Now encapsulate in the ICMP */ sr_icmp_hdr_t* ih = (sr_icmp_hdr_t*)(packet+sizeof(sr_ip_hdr_t)); if( (ip_header->ip_p == ICMP_PROTOCOL) && (ih->icmp_type != 8) ) { /* Dont send an ICMP for ICMP */ return; } print_hdr_ip(packet); int size = sizeof(sr_ip_hdr_t)+sizeof(sr_icmp_hdr_t)+sizeof(sr_ip_hdr_t)+8; uint8_t* complete_packet = (uint8_t*) malloc(sizeof(uint8_t)*size); uint8_t* icmp_start = make_ICMP(sr,packet,len,3,0); struct sr_if* src_if = sr_get_interface(sr,packet_src_iface); uint8_t* ip_start = make_IP_packet(*((uint8_t*)ip_header),(0x0000), htons(size), 0x0000, 0x0000,64,0x01, \ src_if->ip,ip_header->ip_src); /* Foreward the ICMP packet with 3,0 to the src host */ /* If the entry is again wrong, then dont send the ICMP for ICMP */ memcpy(complete_packet,ip_start,sizeof(sr_ip_hdr_t)); memcpy(complete_packet+sizeof(sr_ip_hdr_t),icmp_start,sizeof(sr_icmp_hdr_t)+sizeof(sr_ip_hdr_t)+8); forward_packet(sr,complete_packet,size,packet_src_iface); return; } /* Now query for the Ethernet details */ /* Get the router interface from where the packet should leave */ struct sr_if* src_interface = sr_get_interface(sr,target->interface); /* Get the ARP entry for the next hop IP */ struct sr_arpentry* entry = sr_arpcache_lookup(&sr->cache,(target->gw.s_addr)); /* Now build the ethernet header */ uint8_t* complete_packet = (uint8_t*)malloc(sizeof(sr_ethernet_hdr_t)+len); memcpy(complete_packet+sizeof(sr_ethernet_hdr_t),packet,len); /* Fill in all the details of the ethernet */ sr_ethernet_hdr_t* eth_hdr = (sr_ethernet_hdr_t*)complete_packet; memcpy(eth_hdr->ether_shost,src_interface->addr,sizeof(uint8_t)*6); eth_hdr->ether_type = htons(IP_PROTOCOL); /* If entry is NULL, It means that there is no cache entry in ARP Table */ /* If not NULL, Then use the entry for next hop MAC address */ /*assert(entry!=NULL);*/ if( entry == NULL ) { /* Destination MAC is not known ! */ memset(eth_hdr->ether_dhost,0,sizeof(uint8_t)*6); /* Cache doesnt have this entry, So request it */ struct sr_arpreq* req = sr_arpcache_queuereq(&sr->cache,target->gw.s_addr,complete_packet,len+sizeof(sr_ethernet_hdr_t) \ ,target->interface); assert(req!=NULL); /* Free the packet, as we dont need it. It has been copied to other buffer in the request queue */ handle_ARP_req(sr, &sr->cache,req); } else { /* Destination MAC is known, So use it! */ memcpy(eth_hdr->ether_dhost,entry->mac,sizeof(uint8_t)*6); /* Now send the packet to the target interface */ sr_send_packet(sr,complete_packet,sizeof(sr_ethernet_hdr_t)+len,target->interface); free(entry); } }