static int prepare4(struct rxe_pkt_info *pkt, struct sk_buff *skb) { struct rxe_qp *qp = pkt->qp; struct dst_entry *dst; bool xnet = false; __be16 df = htons(IP_DF); struct rxe_av *av = rxe_get_av(pkt); struct in_addr *saddr = &av->sgid_addr._sockaddr_in.sin_addr; struct in_addr *daddr = &av->dgid_addr._sockaddr_in.sin_addr; dst = rxe_find_route(skb->dev, qp, av); if (!dst) { pr_err("Host not reachable\n"); return -EHOSTUNREACH; } prepare_udp_hdr(skb, cpu_to_be16(qp->src_port), cpu_to_be16(ROCE_V2_UDP_DPORT)); prepare_ipv4_hdr(dst, skb, saddr->s_addr, daddr->s_addr, IPPROTO_UDP, av->grh.traffic_class, av->grh.hop_limit, df, xnet); dst_release(dst); return 0; }
void sr_handle_arpreq(struct sr_instance* sr /* borrowed */, struct sr_arpreq* req /* borrowed */) { time_t now = time(NULL); if( 1.0 <= difftime(now,req->sent) ) { if( 5 <= req->times_sent ) { unsigned int len = sizeof(sr_ethernet_hdr_t)+sizeof(sr_ip_hdr_t)+sizeof(sr_icmp_t3_hdr_t); uint8_t* buf = (uint8_t*)malloc(len); struct sr_rt* rt_match = 0; sr_ip_hdr_t* ip_hdr = 0; sr_ethernet_hdr_t* eth_hdr = 0; struct sr_if* if_to_send = 0; assert(buf); while(req->packets) { ip_hdr = (sr_ip_hdr_t*)(req->packets->buf+sizeof(sr_ethernet_hdr_t)); eth_hdr = (sr_ethernet_hdr_t*)(req->packets->buf); rt_match = sr_get_longest_rt_table_match(sr->routing_table,ip_hdr->ip_src); if(rt_match) { if_to_send = sr_get_interface(sr,rt_match->interface); prepare_icmp_t3_hdr( (sr_icmp_t3_hdr_t*)( buf+(len-sizeof(sr_icmp_t3_hdr_t)) ), 0x03 /* type */, 0x01/* code */, ip_hdr ); /* Note: Not looking at rt_table for mac, just reusing mac->IP from existing queued packet */ prepare_ipv4_hdr((sr_ip_hdr_t*)(buf+sizeof(sr_ethernet_hdr_t)),0x00 /* TOS */, len-sizeof(sr_ethernet_hdr_t), 0x0000 /* ID */, IP_DF /* offset */, ip_protocol_icmp /* protocol */, ntohl(if_to_send->ip) /* source */ ,ntohl(ip_hdr->ip_src) /* destination */); prepare_eth_hdr((sr_ethernet_hdr_t*)buf, eth_hdr->ether_shost /* destination */, if_to_send->addr /* sender */, ethertype_ip); sr_send_packet(sr,buf,len,rt_match->interface); } req->packets = req->packets->next; } free(buf); fprintf(stderr,"Sent ICMP host not reachable (type 3, code 1)\n"); sr_arpreq_destroy(&sr->cache,req); } else { /* Send a ARP request */ unsigned int len = sizeof(sr_ethernet_hdr_t)+sizeof(sr_arp_hdr_t); uint8_t* buf = (uint8_t*)malloc(len); struct sr_if* if_to_send = sr_get_interface(sr,req->packets->iface); assert(buf); sr_ethernet_hdr_t* eth_hdr = (sr_ethernet_hdr_t*)buf; sr_arp_hdr_t* arp_req = (sr_arp_hdr_t*)(buf+sizeof(sr_ethernet_hdr_t)); /* Prepare Ethernet Header */ memset(eth_hdr->ether_dhost,0xff,ETHER_ADDR_LEN); memcpy(eth_hdr->ether_shost,if_to_send->addr,ETHER_ADDR_LEN); eth_hdr->ether_type = htons(ethertype_arp); /* Prepare ARP request */ arp_req->ar_hrd = htons(arp_hrd_ethernet); arp_req->ar_pro = htons(ethertype_ip); arp_req->ar_hln = ETHER_ADDR_LEN; arp_req->ar_pln = 0x04; arp_req->ar_op = htons(arp_op_request); memcpy(arp_req->ar_sha,if_to_send->addr,ETHER_ADDR_LEN); arp_req->ar_sip = if_to_send->ip; memset(arp_req->ar_tha,0xff,ETHER_ADDR_LEN); arp_req->ar_tip = req->ip; fprintf(stderr, "Sending ARP request\n"); sr_send_packet(sr,buf,len,if_to_send->name); free(buf); req->sent = time(NULL); req->times_sent++; } } }