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));
}
Esempio n. 2
0
// 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;
}