コード例 #1
0
shared_ptr<Interface> ThriftConfigApplier::updateInterface(
    const shared_ptr<Interface>& orig,
    const cfg::Interface* config,
    const Interface::Addresses& addrs) {
    CHECK_EQ(orig->getID(), config->intfID);

    cfg::NdpConfig ndp;
    if (config->__isset.ndp) {
        ndp = config->ndp;
    }
    auto name = getInterfaceName(config);
    auto mac = getInterfaceMac(config);
    auto mtu = config->__isset.mtu ? config->mtu : Interface::kDefaultMtu;
    if (orig->getRouterID() == RouterID(config->routerID) &&
            orig->getVlanID() == VlanID(config->vlanID) &&
            orig->getName() == name &&
            orig->getMac() == mac &&
            orig->getAddresses() == addrs &&
            orig->getNdpConfig() == ndp &&
            orig->getMtu() == mtu) {
        // No change
        return nullptr;
    }

    auto newIntf = orig->clone();
    newIntf->setRouterID(RouterID(config->routerID));
    newIntf->setVlanID(VlanID(config->vlanID));
    newIntf->setName(name);
    newIntf->setMac(mac);
    newIntf->setAddresses(addrs);
    newIntf->setNdpConfig(ndp);
    newIntf->setMtu(mtu);
    return newIntf;
}
コード例 #2
0
Interface::Addresses ThriftConfigApplier::getInterfaceAddresses(
    const cfg::Interface* config) {
    Interface::Addresses addrs;
    for (const auto& addr : config->ipAddresses) {
        auto intfAddr = IPAddress::createNetwork(addr, -1, false);
        auto ret = addrs.insert(intfAddr);
        if (!ret.second) {
            throw FbossError("Duplicate network IP address ", addr,
                             " in interface ", config->intfID);
        }
        auto ret2 = intfRouteTables_[RouterID(config->routerID)].emplace(
                        IPAddress::createNetwork(addr),
                        std::make_pair(InterfaceID(config->intfID), intfAddr.first));
        if (!ret2.second) {
            // we get same network, only allow it if that is from the same interface
            auto other = ret2.first->second.first;
            if (other != InterfaceID(config->intfID)) {
                throw FbossError("Duplicate network address ", addr, " of interface ",
                                 config->intfID, " as interface ", other,
                                 " in VRF ", config->routerID);
            }
        }
    }
    return addrs;
}
コード例 #3
0
ファイル: IPv4Handler.cpp プロジェクト: HengWang/fboss
// 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;
}
コード例 #4
0
ファイル: Interface.cpp プロジェクト: Gardenya/fboss
InterfaceFields InterfaceFields::fromFollyDynamic(const folly::dynamic& json) {
  auto intfFields =
    InterfaceFields(InterfaceID(json[kIntfId].asInt()),
      RouterID(json[kRouterId].asInt()), VlanID(json[kVlanId].asInt()),
      json[kName].asString(), MacAddress(json[kMac].asString()));
  ThriftSerializerJson<cfg::NdpConfig> serializer;
  for (const auto& addr: json[kAddresses]) {
    auto cidr = IPAddress::createNetwork(addr.asString(),
          -1 /*use /32 for v4 and /128 for v6*/,
        false /*don't apply mask*/);
    intfFields.addrs[cidr.first] = cidr.second;
  }
  serializer.deserialize(toJson(json[kNdpConfig]),
      &intfFields.ndp);
  return intfFields;
}
コード例 #5
0
shared_ptr<Interface> ThriftConfigApplier::createInterface(
    const cfg::Interface* config,
    const Interface::Addresses& addrs) {
    auto name = getInterfaceName(config);
    auto mac = getInterfaceMac(config);
    auto mtu = config->__isset.mtu ? config->mtu : Interface::kDefaultMtu;
    auto intf = make_shared<Interface>(InterfaceID(config->intfID),
                                       RouterID(config->routerID),
                                       VlanID(config->vlanID),
                                       name,
                                       mac,
                                       mtu);
    intf->setAddresses(addrs);
    if (config->__isset.ndp) {
        intf->setNdpConfig(config->ndp);
    }
    return intf;
}
コード例 #6
0
ファイル: IPv4Handler.cpp プロジェクト: HengWang/fboss
void IPv4Handler::handlePacket(unique_ptr<RxPacket> pkt,
                               MacAddress dst,
                               MacAddress src,
                               Cursor cursor) {
  SwitchStats* stats = sw_->stats();
  PortID port = pkt->getSrcPort();

  const uint32_t l3Len = pkt->getLength() - (cursor - Cursor(pkt->buf()));
  stats->port(port)->ipv4Rx();
  IPv4Hdr v4Hdr(cursor);
  VLOG(4) << "Rx IPv4 packet (" << l3Len << " bytes) " << v4Hdr.srcAddr.str()
          << " --> " << v4Hdr.dstAddr.str()
          << " proto: 0x" << std::hex << static_cast<int>(v4Hdr.protocol);

  // retrieve the current switch state
  auto state = sw_->getState();
  // Need to check if the packet is for self or not. We store our IP
  // in the ARP response table. Use that for now.
  auto vlan = state->getVlans()->getVlanIf(pkt->getSrcVlan());
  if (!vlan) {
    stats->port(port)->pktDropped();
    return;
  }

  if (v4Hdr.protocol == IPPROTO_UDP) {
    Cursor udpCursor(cursor);
    UDPHeader udpHdr;
    udpHdr.parse(sw_, port, &udpCursor);
    VLOG(4) << "UDP packet, Source port :" << udpHdr.srcPort
        << " destination port: " << udpHdr.dstPort;
    if (DHCPv4Handler::isDHCPv4Packet(udpHdr)) {
      DHCPv4Handler::handlePacket(sw_, std::move(pkt), src, dst, v4Hdr,
          udpHdr, udpCursor);
      return;
    }
  }

  auto dstIP = v4Hdr.dstAddr;
  // Handle packets destined for us
  // TODO: assume vrf 0 now
  if (state->getInterfaces()->getInterfaceIf(RouterID(0), IPAddress(dstIP))) {
    // TODO: Also check to see if this is the broadcast address for one of the
    // interfaces on this VLAN.  We should probably build up a more efficient
    // data structure to look up this information.
    stats->port(port)->ipv4Mine();
    // Anything not handled by the controller, we will forward it to the host,
    // i.e. ping, ssh, bgp...
    // FixME: will do another diff to set length in RxPacket, so that it
    // can be reused here.
    if (sw_->sendPacketToHost(std::move(pkt))) {
      stats->port(port)->pktToHost(l3Len);
    } else {
      stats->port(port)->pktDropped();
    }
    return;
  }

  // if packet is not for us, check the ttl exceed
  if (v4Hdr.ttl <= 1) {
    VLOG(4) << "Rx IPv4 Packet with TTL expired";
    stats->port(port)->pktDropped();
    stats->port(port)->ipv4TtlExceeded();
    // Look up cpu mac from platform
    MacAddress cpuMac = sw_->getPlatform()->getLocalMac();
    sendICMPTimeExceeded(pkt->getSrcVlan(), cpuMac, cpuMac, v4Hdr, cursor);
    return;
  }

  // Handle broadcast packets.
  // TODO: Also check to see if this is the broadcast address for one of the
  // interfaces on this VLAN. We should probably build up a more efficient
  // data structure to look up this information.
  if (dstIP.isLinkLocalBroadcast()) {
    stats->port(port)->pktDropped();
    return;
  }

  // TODO: check the reason of punt, for now, assume it is for
  // resolving the address
  // We will need to manage the rate somehow. Either from HW
  // or a SW control here
  stats->port(port)->ipv4Nexthop();
  if (!resolveMac(state.get(), dstIP)) {
    stats->port(port)->ipv4NoArp();
    VLOG(3) << "Cannot find the interface to send out ARP request for "
      << dstIP.str();
  }
  // TODO: ideally, we need to store this packet until the ARP is done and
  // then send this pkt out. For now, just drop it.
  stats->port(port)->pktDropped();
}
コード例 #7
0
ファイル: TunIntf.cpp プロジェクト: Gardenya/fboss
RouterID TunIntf::getRidFromName(const char *name) {
  if (!isTunIntf(name)) {
    throw FbossError(name, " is not a valid tun interface");
  }
  return RouterID(atoi(name + prefixLen));
}