enum ofp_return_code ofp_arp_processing(odp_packet_t *pkt) { struct ofp_arphdr *arp; struct ofp_ifnet *dev = odp_packet_user_ptr(*pkt); struct ofp_ifnet *outdev = dev; uint16_t vlan = dev->vlan; uint8_t inner_from_mac[OFP_ETHER_ADDR_LEN]; uint32_t is_ours; arp = (struct ofp_arphdr *)odp_packet_l3_ptr(*pkt, NULL); if (odp_unlikely(arp == NULL)) { OFP_DBG("arp is NULL"); return OFP_PKT_DROP; } /* save the received arp info */ if (odp_be_to_cpu_16(arp->op) == OFP_ARPOP_REPLY) ofp_add_mac(dev, arp->ip_src, arp->eth_src); OFP_DBG("Device IP: %s, Packet Dest IP: %s", ofp_print_ip_addr(dev->ip_addr), ofp_print_ip_addr(arp->ip_dst)); /* Check for VXLAN interface */ if (odp_unlikely(ofp_if_type(dev) == OFP_IFT_VXLAN)) { ofp_vxlan_update_devices(*pkt, arp, &vlan, &dev, &outdev, inner_from_mac); } is_ours = dev->ip_addr && dev->ip_addr == (ofp_in_addr_t)(arp->ip_dst); if (!is_ours && !global_param->arp.check_interface) { /* This may be for some other local interface. */ uint32_t flags; struct ofp_nh_entry *nh; nh = ofp_get_next_hop(dev->vrf, arp->ip_dst, &flags); if (nh) is_ours = nh->flags & OFP_RTF_LOCAL; } /* on our interface an ARP request */ if (is_ours && odp_be_to_cpu_16(arp->op) == OFP_ARPOP_REQUEST) { struct ofp_arphdr tmp; struct ofp_ether_header tmp_eth; struct ofp_ether_vlan_header tmp_eth_vlan; void *l2_addr = odp_packet_l2_ptr(*pkt, NULL); struct ofp_ether_header *eth = (struct ofp_ether_header *)l2_addr; struct ofp_ether_vlan_header *eth_vlan = (struct ofp_ether_vlan_header *)l2_addr; ofp_add_mac(dev, arp->ip_src, arp->eth_src); if (vlan) tmp_eth_vlan = *eth_vlan; else tmp_eth = *eth; OFP_DBG("Reply to ARPOP_REQ from ip %s" #ifdef SP "on IF %d" #endif " mac %s ip %s", ofp_print_ip_addr(arp->ip_src), #ifdef SP dev->linux_index, #endif ofp_print_mac(dev->mac), ofp_print_ip_addr(arp->ip_dst)); tmp = *arp; tmp.ip_dst = arp->ip_src; tmp.ip_src = arp->ip_dst; memcpy(&tmp.eth_dst, &arp->eth_src, OFP_ETHER_ADDR_LEN); memcpy(&tmp.eth_src, dev->mac, OFP_ETHER_ADDR_LEN); tmp.op = odp_cpu_to_be_16(OFP_ARPOP_REPLY); *arp = tmp; if (vlan) { memcpy(tmp_eth_vlan.evl_dhost, &arp->eth_dst, OFP_ETHER_ADDR_LEN); memcpy(tmp_eth_vlan.evl_shost, &arp->eth_src, OFP_ETHER_ADDR_LEN); *eth_vlan = tmp_eth_vlan; } else { memcpy(tmp_eth.ether_dhost, &arp->eth_dst, OFP_ETHER_ADDR_LEN); memcpy(tmp_eth.ether_shost, &arp->eth_src, OFP_ETHER_ADDR_LEN); *eth = tmp_eth; } if (odp_unlikely(ofp_if_type(dev) == OFP_IFT_VXLAN)) { /* Restore the original vxlan header and update the addresses */ ofp_vxlan_restore_and_update_header (*pkt, outdev, inner_from_mac); } return send_pkt_out(outdev, *pkt); } return OFP_PKT_CONTINUE; }
enum ofp_return_code ofp_arp_processing(odp_packet_t pkt) { struct ofp_arphdr *arp; struct ofp_ifnet *dev = odp_packet_user_ptr(pkt); struct ofp_ifnet *outdev = dev; uint16_t vlan = dev->vlan; uint8_t inner_from_mac[OFP_ETHER_ADDR_LEN]; arp = (struct ofp_arphdr *)odp_packet_l3_ptr(pkt, NULL); if (odp_unlikely(arp == NULL)) { OFP_DBG("arp is NULL"); return OFP_PKT_DROP; } /* save the received arp info */ if (odp_be_to_cpu_16(arp->op) == OFP_ARPOP_REPLY) ofp_add_mac(dev, arp->ip_src, arp->eth_src); OFP_DBG("Device IP: %s, Packet Dest IP: %s", ofp_print_ip_addr(dev->ip_addr), ofp_print_ip_addr(arp->ip_dst)); /* Check for VXLAN interface */ if (odp_unlikely(!PHYS_PORT(dev->port))) { switch (dev->port) { case GRE_PORTS: /* Never happens. */ break; case VXLAN_PORTS: { ofp_vxlan_update_devices(arp, &vlan, &dev, &outdev, inner_from_mac); break; } } /* switch */ } /* on our interface an ARP request */ if ((dev->ip_addr) && dev->ip_addr == (ofp_in_addr_t)(arp->ip_dst) && odp_be_to_cpu_16(arp->op) == OFP_ARPOP_REQUEST) { struct ofp_arphdr tmp; struct ofp_ether_header tmp_eth; struct ofp_ether_vlan_header tmp_eth_vlan; void *l2_addr = odp_packet_l2_ptr(pkt, NULL); struct ofp_ether_header *eth = (struct ofp_ether_header *)l2_addr; struct ofp_ether_vlan_header *eth_vlan = (struct ofp_ether_vlan_header *)l2_addr; ofp_add_mac(dev, arp->ip_src, arp->eth_src); if (vlan) tmp_eth_vlan = *eth_vlan; else tmp_eth = *eth; OFP_DBG("Reply to ARPOP_REQ from ip %s" #ifdef SP "on IF %d" #endif " mac %s ip %s", ofp_print_ip_addr(arp->ip_src), #ifdef SP dev->linux_index, #endif ofp_print_mac(dev->mac), ofp_print_ip_addr(arp->ip_dst)); tmp = *arp; tmp.ip_dst = arp->ip_src; tmp.ip_src = arp->ip_dst; memcpy(&tmp.eth_dst, &arp->eth_src, OFP_ETHER_ADDR_LEN); memcpy(&tmp.eth_src, dev->mac, OFP_ETHER_ADDR_LEN); tmp.op = odp_cpu_to_be_16(OFP_ARPOP_REPLY); *arp = tmp; if (vlan) { memcpy(tmp_eth_vlan.evl_dhost, &arp->eth_dst, OFP_ETHER_ADDR_LEN); memcpy(tmp_eth_vlan.evl_shost, &arp->eth_src, OFP_ETHER_ADDR_LEN); *eth_vlan = tmp_eth_vlan; } else { memcpy(tmp_eth.ether_dhost, &arp->eth_dst, OFP_ETHER_ADDR_LEN); memcpy(tmp_eth.ether_shost, &arp->eth_src, OFP_ETHER_ADDR_LEN); *eth = tmp_eth; } if (odp_unlikely(!PHYS_PORT(dev->port))) { switch (dev->port) { case GRE_PORTS: /* Never happens. */ break; case VXLAN_PORTS: { /* Restore the original vxlan header and update the addresses */ ofp_vxlan_restore_and_update_header (pkt, outdev, inner_from_mac); break; } } /* switch */ } /* not phys port */ return send_pkt_out(outdev, pkt); } return OFP_PKT_CONTINUE; }