static int add_invalid_neighbor6(neighbor_struct_t *neighbor_struct, struct in6_addr *ip, uint16_t dst_port) { struct ether_addr invalid_mac = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; uint8_t nexthop_id; if (neighbor6_add_nexthop(neighbor_struct, ip, &nexthop_id, NEI_ACTION_DROP) < 0) { return -1; } neighbor6_refcount_incr(neighbor_struct, nexthop_id); neighbor6_set_lladdr_port(neighbor_struct, nexthop_id, &invalid_mac, &invalid_mac, dst_port, -1); return 0; }
static int neighbor6(neighbor_action_t action, int32_t port_id, struct in6_addr* addr, struct ether_addr* lladdr, uint8_t flags, __rte_unused uint16_t vlan_id, void* args) { // if port_id is not handled // ignore, return immediatly // if neighbor add // lookup neighbor // if exists // update lladdr, set flag as REACHABLE/STALE/DELAY // else // // This should not happen // insert new nexthop // set insert date=now, refcount = 0, flag=REACHABLE/STALE/DELAY // if neighbor delete // lookup neighbor // if exists // if refcount != 0 // set nexthop as invalid // else // set flag empty // else // do nothing // // this should not happen struct control_handle* handle = args; assert(handle != NULL); int s; uint16_t nexthop_id, find_id; int32_t socket_id = handle->socket_id; char ipbuf[INET6_ADDRSTRLEN]; assert(neighbor6_struct != NULL); if (addr == NULL) return -1; inet_ntop(AF_INET6, addr, ipbuf, INET6_ADDRSTRLEN); if (action == NEIGHBOR_ADD) { if (lladdr == NULL) return -1; char ibuf[IFNAMSIZ]; unsigned kni_vlan; if_indextoname(port_id, ibuf); s = sscanf(ibuf, "dpdk%10u.%10u", &port_id, &kni_vlan); if (s <= 0) { RTE_LOG(ERR, PKTJ_CTRL1, "received a neighbor " "announce for an unmanaged " "iface %s\n", ibuf); return -1; } s = neighbor6_lookup_nexthop(neighbor6_struct[socket_id], addr, &nexthop_id); if (s < 0) { if (flags != NUD_NONE && flags != NUD_NOARP && flags != NUD_STALE) { RTE_LOG(ERR, PKTJ_CTRL1, "failed to change state in neighbor6 " "table (state %d, %s)...\n", flags, ipbuf); return -1; } { RTE_LOG( DEBUG, PKTJ_CTRL1, "adding ipv6 neighbor %s with port_id %d " "vlan_id %d...\n", ipbuf, port_id, kni_vlan); } s = neighbor6_add_nexthop(neighbor6_struct[socket_id], addr, &nexthop_id, NEI_ACTION_FWD); if (s < 0) { RTE_LOG(ERR, PKTJ_CTRL1, "failed to add a " "nexthop in neighbor " "table...\n"); return -1; } // apply rate limit rule if next hop neighbor is in the // table apply_rate_limit_ipv6(addr, nexthop_id, socket_id); if (rte_lpm6_lookup(ipv6_pktj_lookup_struct[socket_id], addr->s6_addr, &find_id) == 0) { s = rte_lpm6_add( ipv6_pktj_lookup_struct[socket_id], addr->s6_addr, 128, nexthop_id); if (s < 0) { lpm6_stats[socket_id].nb_add_ko++; RTE_LOG(ERR, PKTJ_CTRL1, "failed to add a route in " "lpm during neighbor " "adding...\n"); return -1; } lpm6_stats[socket_id].nb_add_ok++; } } if (flags == NUD_FAILED) { neighbor6_set_action(neighbor6_struct[socket_id], nexthop_id, NEI_ACTION_KNI); } else { neighbor6_set_action(neighbor6_struct[socket_id], nexthop_id, NEI_ACTION_FWD); } RTE_LOG(DEBUG, PKTJ_CTRL1, "set neighbor6 with port_id %d state %d \n", port_id, flags); neighbor6_set_lladdr_port(neighbor6_struct[socket_id], nexthop_id, &ports_eth_addr[port_id], lladdr, port_id, kni_vlan); neighbor6_set_state(neighbor6_struct[socket_id], nexthop_id, flags); } if (action == NEIGHBOR_DELETE) { if (flags != NUD_FAILED && flags != NUD_STALE) { RTE_LOG( DEBUG, PKTJ_CTRL1, "neighbor6 delete ope failed, bad NUD state: %d \n", flags); return -1; } RTE_LOG(DEBUG, PKTJ_CTRL1, "deleting ipv6 neighbor...\n"); s = neighbor6_lookup_nexthop(neighbor6_struct[socket_id], addr, &nexthop_id); if (s < 0) { RTE_LOG(ERR, PKTJ_CTRL1, "failed to find a nexthop to " "delete in neighbor " "table...\n"); return 0; } neighbor6_delete(neighbor6_struct[socket_id], nexthop_id); // FIXME not thread safe if (neighbor6_struct[socket_id] ->entries.t6[nexthop_id] .neighbor.refcnt == 0) { s = rte_lpm6_delete(ipv6_pktj_lookup_struct[socket_id], addr->s6_addr, 128); if (s < 0) { lpm6_stats[socket_id].nb_del_ko++; RTE_LOG(ERR, PKTJ_CTRL1, "failed to delete route...\n"); return -1; } // reset rate limit for this id rlimit6_max[socket_id][nexthop_id] = UINT32_MAX; lpm6_stats[socket_id].nb_del_ok++; } } RTE_LOG(DEBUG, PKTJ_CTRL1, "neigh %s ope success\n", ipbuf); return 0; }