std::shared_ptr<InterfaceMap> ThriftConfigApplier::updateInterfaces() { auto origIntfs = orig_->getInterfaces(); InterfaceMap::NodeContainer newIntfs; bool changed = false; // Process all supplied interface configs size_t numExistingProcessed = 0; for (const auto& interfaceCfg : cfg_->interfaces) { InterfaceID id(interfaceCfg.intfID); auto origIntf = origIntfs->getInterfaceIf(id); shared_ptr<Interface> newIntf; auto newAddrs = getInterfaceAddresses(&interfaceCfg); if (origIntf) { newIntf = updateInterface(origIntf, &interfaceCfg, newAddrs); ++numExistingProcessed; } else { newIntf = createInterface(&interfaceCfg, newAddrs); } updateVlanInterfaces(newIntf ? newIntf.get() : origIntf.get()); changed |= updateMap(&newIntfs, origIntf, newIntf); } if (numExistingProcessed != origIntfs->size()) { // Some existing interfaces were removed. CHECK_LT(numExistingProcessed, origIntfs->size()); changed = true; } if (!changed) { return nullptr; } return origIntfs->clone(std::move(newIntfs)); }
// Return true if we successfully sent an ARP request, false otherwise bool IPv4Handler::resolveMac(SwitchState* state, IPAddressV4 dest) { // need to find out our own IP and MAC addresses so that we can send the // ARP request out. Since the request will be broadcast, there is no need to // worry about which port to send the packet out. // TODO: assume vrf 0 now auto routeTable = state->getRouteTables()->getRouteTableIf(RouterID(0)); if (!routeTable) { throw FbossError("No routing tables found"); } auto route = routeTable->getRibV4()->longestMatch(dest); if (!route || !route->isResolved()) { // No way to reach dest return false; } auto intfs = state->getInterfaces(); auto nhs = route->getForwardInfo().getNexthops(); for (auto nh : nhs) { auto intf = intfs->getInterfaceIf(nh.intf); if (intf) { auto source = intf->getAddressToReach(nh.nexthop)->first.asV4(); auto target = route->isConnected() ? dest : nh.nexthop.asV4(); if (source == target) { // This packet is for us. Don't send ARP requess for our own IP. continue; } auto vlanID = intf->getVlanID(); auto vlan = state->getVlans()->getVlanIf(vlanID); if (vlan) { auto entry = vlan->getArpTable()->getEntryIf(target); if (entry == nullptr) { // No entry in ARP table, send ARP request auto mac = intf->getMac(); ArpHandler::sendArpRequest(sw_, vlanID, mac, source, target); // Notify the updater that we sent an arp request sw_->getNeighborUpdater()->sentArpRequest(vlanID, target); } else { VLOG(4) << "not sending arp for " << target.str() << ", " << ((entry->isPending()) ? "pending " : "") << "entry already exists"; } } } } return true; }