Beispiel #1
0
int TunManager::getLinkRespParser(const struct sockaddr_nl *who,
                                  struct nlmsghdr *n,
                                  void *arg) {
  // only cares about RTM_NEWLINK
  if (n->nlmsg_type != RTM_NEWLINK) {
    return 0;
  }

  struct ifinfomsg *ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(n));
  struct rtattr *tb[IFLA_MAX + 1];
  int len = n->nlmsg_len;
  len -= NLMSG_LENGTH(sizeof(*ifi));
  if (len < 0) {
    throw FbossError("Wrong length for RTM_GETLINK response ", len, " vs ",
                     NLMSG_LENGTH(sizeof(*ifi)));
  }
  parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
  if (tb[IFLA_IFNAME] == nullptr) {
    throw FbossError("Device @ index ", static_cast<int>(ifi->ifi_index),
                     " does not have a nmae");
  }
  const auto name = rta_getattr_str(tb[IFLA_IFNAME]);
  // match the interface name against intfPrefix
  if (!TunIntf::isTunIntf(name)) {
    VLOG(3) << "Ignore interface " << name
            << " because it is not a tun interface";
    return 0;
  }
  // base on the name, get the router ID
  auto rid = TunIntf::getRidFromName(name);

  TunManager *mgr = static_cast<TunManager *>(arg);
  mgr->addIntf(rid, std::string(name), ifi->ifi_index);
  return 0;
}
Beispiel #2
0
BcmPortGroup::BcmPortGroup(BcmSwitch* hw,
                           BcmPort* controllingPort,
                           std::vector<BcmPort*> allPorts)
    : hw_(hw),
      controllingPort_(controllingPort),
      allPorts_(std::move(allPorts)) {

  if (allPorts_.size() != 4) {
    throw FbossError("Port groups must have exactly four members");
  }

  for (int i = 0; i < allPorts_.size(); ++i) {
    if (getLane(allPorts_[i]) != i) {
      throw FbossError("Ports passed in are not ordered by lane");
    }
  }

  // get the number of active lanes
  auto activeLanes = retrieveActiveLanes();
  switch (activeLanes) {
    case 1:
      laneMode_ = LaneMode::QUAD;
      break;
    case 2:
      laneMode_ = LaneMode::DUAL;
      break;
    case 4:
      laneMode_ = LaneMode::SINGLE;
      break;
    default:
      throw FbossError("Unexpected number of lanes retrieved for bcm port ",
                       controllingPort_->getBcmPortId());
  }

}
Beispiel #3
0
const uint8_t* QsfpModule::getQsfpValuePtr(int dataAddress, int offset,
                                           int length) const {
  /* if the cached values are not correct */
  if (!cacheIsValid()) {
    throw FbossError("Qsfp is either not present or the data is not read");
  }
  if (dataAddress == QsfpPages::LOWER) {
    CHECK_LE(offset + length, sizeof(qsfpIdprom_));
    /* Copy data from the cache */
    return(qsfpIdprom_ + offset);
  } else {
    offset -= MAX_QSFP_PAGE_SIZE;
    CHECK_GE(offset, 0);
    CHECK_LE(offset, MAX_QSFP_PAGE_SIZE);
    if (dataAddress == QsfpPages::PAGE0) {
      CHECK_LE(offset + length, sizeof(qsfpPage0_));
      /* Copy data from the cache */
      return(qsfpPage0_ + offset);
    } else if (dataAddress == QsfpPages::PAGE3 && !flatMem_) {
      CHECK_LE(offset + length, sizeof(qsfpPage3_));
      /* Copy data from the cache */
      return(qsfpPage3_ + offset);
    } else {
      throw FbossError("Invalid Data Address 0x%d", dataAddress);
    }
  }
}
bool ThriftConfigApplier::updateDhcpOverrides(Vlan* vlan,
        const cfg::Vlan* config) {
    DhcpV4OverrideMap newDhcpV4OverrideMap;
    for (const auto& pair : config->dhcpRelayOverridesV4) {
        try {
            newDhcpV4OverrideMap[MacAddress(pair.first)] = IPAddressV4(pair.second);
        } catch (const IPAddressFormatException& ex) {
            throw FbossError("Invalid IPv4 address in DHCPv4 relay override map: ",
                             ex.what());
        }
    }

    DhcpV6OverrideMap newDhcpV6OverrideMap;
    for (const auto& pair : config->dhcpRelayOverridesV6) {
        try {
            newDhcpV6OverrideMap[MacAddress(pair.first)] = IPAddressV6(pair.second);
        } catch (const IPAddressFormatException& ex) {
            throw FbossError("Invalid IPv4 address in DHCPv4 relay override map: ",
                             ex.what());
        }
    }

    bool changed = false;
    auto oldDhcpV4OverrideMap = vlan->getDhcpV4RelayOverrides();
    if (oldDhcpV4OverrideMap != newDhcpV4OverrideMap) {
        vlan->setDhcpV4RelayOverrides(newDhcpV4OverrideMap);
        changed = true;
    }
    auto oldDhcpV6OverrideMap = vlan->getDhcpV6RelayOverrides();
    if (oldDhcpV6OverrideMap != newDhcpV6OverrideMap) {
        vlan->setDhcpV6RelayOverrides(newDhcpV6OverrideMap);
        changed = true;
    }
    return changed;
}
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;
}
Beispiel #6
0
BcmPortGroup::LaneMode BcmPortGroup::calculateDesiredLaneMode(
    const std::vector<Port*>& ports, LaneSpeeds laneSpeeds) {
  auto desiredMode = LaneMode::QUAD;
  for (int lane = 0; lane < ports.size(); ++lane) {
    auto port = ports[lane];
    if (!port->isDisabled()) {
      auto neededMode = neededLaneModeForSpeed(port->getSpeed(), laneSpeeds);
      if (neededMode < desiredMode) {
        desiredMode = neededMode;
      }

      // Check that the lane is expected for SINGLE/DUAL modes
      if (desiredMode == LaneMode::SINGLE) {
        if (lane != 0) {
          throw FbossError("Only lane 0 can be enabled in SINGLE mode");
        }
      } else if (desiredMode == LaneMode::DUAL) {
        if (lane != 0 && lane != 2) {
          throw FbossError("Only lanes 0 or 2 can be enabled in DUAL mode");
        }
      }

      VLOG(3) << "Port " << port->getID() << " enabled with speed " <<
        static_cast<int>(port->getSpeed());
    }
  }
  return desiredMode;
}
Beispiel #7
0
std::string RestClient::requestWithOutput(std::string path) {
  CURL* curl;
  CURLcode resp;
  std::stringbuf write_buffer;
  endpoint_ = endpoint_ + path;
  /* for curl errors */
  char error[CURL_ERROR_SIZE];

  curl = curl_easy_init();
  if (curl) {
    /* Set the curl options */
    curl_easy_setopt(curl, CURLOPT_URL, endpoint_.c_str());
    curl_easy_setopt(curl, CURLOPT_PROTOCOLS,CURLPROTO_HTTP);
    curl_easy_setopt(curl, CURLOPT_PORT, port_);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout_.count());
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, RestClient::writer);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_buffer);
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
    curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);

    /* if an interface is specified use that */
    if (!interface_.empty()) {
      curl_easy_setopt(curl, CURLOPT_INTERFACE, interface_.c_str());
    }

    resp = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
    if (resp == CURLE_OK) {
      return write_buffer.str();
    } else {
      throw FbossError("Error querying api: ", endpoint_, " error: ", error);
    }
  }
  throw FbossError("Error initializing curl interface");
}
Beispiel #8
0
std::unique_ptr<BcmUnit> BcmAPI::initOnlyUnit() {
  auto numDevices = BcmAPI::getNumSwitches();
  if (numDevices == 0) {
    throw FbossError("no Broadcom switching ASIC found");
  } else if (numDevices > 1) {
    throw FbossError("found more than 1 Broadcom switching ASIC");
  }
  return initUnit(0);
}
Beispiel #9
0
BcmUnit* BcmAPI::getUnit(int unit) {
  if (unit < 0 || unit > getMaxSwitches()) {
    throw FbossError("invalid BCM unit number ", unit);
  }
  BcmUnit* unitObj = bcmUnits[unit].load(std::memory_order_acquire);
  if (!unitObj) {
    throw FbossError("no BcmUnit created for unit number ", unit);
  }
  return unitObj;
}
Beispiel #10
0
void IPHeaderV4::parse(SwSwitch *sw, PortID port, Cursor* cursor) {
  auto len = cursor->pullAtMost(&hdr_[0], sizeof(hdr_));
  if (len != sizeof(hdr_)) {
    sw->stats()->port(port)->ipv4TooSmall();
    throw FbossError("Too small packet. Get ", cursor->length(),
                     " bytes. Minimum ", sizeof(hdr_), " bytes");
  }
  if (getVersion() != 4) {
    sw->stats()->port(port)->ipv4WrongVer();
    throw FbossError("Wrong IPv4 version number (", getVersion(), " vs 4)");
  }
  // TODO: other sanity checks (i.e. packet length, checksum...)
}
Beispiel #11
0
WedgePort* WedgePlatform::getPort(PortID id) {
  auto iter = ports_.find(id);
  if (iter == ports_.end()) {
    throw FbossError("Cannot find the Wedge port object for BCM port ", id);
  }
  return iter->second.get();
}
Beispiel #12
0
shared_ptr<NdpCache> NeighborUpdater::getNdpCacheInternal(VlanID vlan) {
  auto res = caches_.find(vlan);
  if (res == caches_.end()) {
    throw FbossError("Tried to get Ndp cache non-existent vlan ", vlan);
  }
  return res->second->ndpCache;
}
 bool updateMap(NodeMap* map, std::shared_ptr<Node> origNode,
                std::shared_ptr<Node> newNode) {
     if (newNode) {
         auto ret = map->insert(std::make_pair(newNode->getID(), newNode));
         if (!ret.second) {
             throw FbossError("duplicate entry ", newNode->getID());
         }
         return true;
     } else {
         auto ret = map->insert(std::make_pair(origNode->getID(), origNode));
         if (!ret.second) {
             throw FbossError("duplicate entry ", origNode->getID());
         }
         return false;
     }
 }
Beispiel #14
0
void TunManager::addIntf(RouterID rid, const Interface::Addresses& addrs) {
  auto ret = intfs_.emplace(rid, nullptr);
  if (!ret.second) {
    throw FbossError("Duplicate interface for router ", rid);
  }
  SCOPE_FAIL {
    intfs_.erase(ret.first);
  };
  auto intf = folly::make_unique<TunIntf>(
      sw_, evb_, rid, addrs, getMinMtu(sw_->getState()));
  SCOPE_FAIL {
    intf->setDelete();
  };
  const auto& name = intf->getName();
  auto index = intf->getIfIndex();
  // bring up the interface so that we can add the default route next step
  bringupIntf(name, index);
  // create a new route table for this rid
  addRouteTable(index, rid);
  // add all addresses
  for (const auto& addr : addrs) {
    addTunAddress(name, rid, index, addr.first, addr.second);
  }
  ret.first->second = std::move(intf);
}
Beispiel #15
0
BcmIntf* BcmIntfTable::getBcmIntf(InterfaceID id) const {
  auto ptr = getBcmIntfIf(id);
  if (ptr == nullptr) {
    throw FbossError("Cannot find interface ", id);
  }
  return ptr;
}
Beispiel #16
0
BcmAclRange* FOLLY_NULLABLE BcmAclTable::derefBcmAclRange(
  const AclRange& range) {
  auto iter = aclRangeMap_.find(range);
  if (iter == aclRangeMap_.end()) {
    throw FbossError("decrease reference count on a non-existing BcmAclRange");
  }
  if (iter->second.second == 0) {
    throw FbossError("dereference a BcmAclRange whose reference is 0");
  }
  iter->second.second--;
  if (iter->second.second == 0) {
    aclRangeMap_.erase(iter);
    return nullptr;
  }
  return iter->second.first.get();
}
void ThriftConfigApplier::updateVlanInterfaces(const Interface* intf) {
    auto& entry = vlanInterfaces_[intf->getVlanID()];

    // Each VLAN can only be used with a single virtual router
    if (entry.interfaces.empty()) {
        entry.routerID = intf->getRouterID();
    } else {
        if (intf->getRouterID() != entry.routerID) {
            throw FbossError("VLAN ", intf->getVlanID(), " configured in multiple "
                             "different virtual routers: ", entry.routerID, " and ",
                             intf->getRouterID());
        }
    }

    auto intfRet = entry.interfaces.insert(intf->getID());
    if (!intfRet.second) {
        // This shouldn't happen
        throw FbossError("interface ", intf->getID(), " processed twice for "
                         "VLAN ", intf->getVlanID());
    }

    for (const auto& ipMask : intf->getAddresses()) {
        VlanIpInfo info(ipMask.second, intf->getMac(), intf->getID());
        auto ret = entry.addresses.emplace(ipMask.first, info);
        if (ret.second) {
            continue;
        }
        // Allow multiple interfaces on the same VLAN with the same IP,
        // as long as they also share the same mask and MAC address.
        const auto& oldInfo = ret.first->second;
        if (oldInfo.mask != info.mask) {
            throw FbossError("VLAN ", intf->getVlanID(), " has IP ", ipMask.first,
                             " configured multiple times with different masks (",
                             oldInfo.mask, " and ", info.mask, ")");
        }
        if (oldInfo.mac != info.mac) {
            throw FbossError("VLAN ", intf->getVlanID(), " has IP ", ipMask.first,
                             " configured multiple times with different MACs (",
                             oldInfo.mac, " and ", info.mac, ")");
        }
    }

    // Also add the link-local IPv6 address
    IPAddressV6 linkLocalAddr(IPAddressV6::LINK_LOCAL, intf->getMac());
    VlanIpInfo linkLocalInfo(64, intf->getMac(), intf->getID());
    entry.addresses.emplace(IPAddress(linkLocalAddr), linkLocalInfo);
}
Beispiel #18
0
InterfaceMap::Interfaces
InterfaceMap::getInterfacesInVlan(VlanID vlan) const {
  auto interfaces = getInterfacesInVlanIf(vlan);
  if (interfaces.empty()) {
    throw FbossError("No interface in vlan : ", vlan);
  }
  return interfaces;
}
Beispiel #19
0
BcmRoute* BcmRouteTable::getBcmRoute(
    opennsl_vrf_t vrf, const folly::IPAddress& network, uint8_t mask) const {
  auto rt = getBcmRouteIf(vrf, network, mask);
  if (!rt) {
    throw FbossError("Cannot find route for ", network,
                     "/", static_cast<uint32_t>(mask), " @ vrf ", vrf);
  }
  return rt;
}
Beispiel #20
0
const std::shared_ptr<Interface>&
InterfaceMap::getInterface(RouterID router, const IPAddress& ip) const {
  for (auto itr = begin(); itr != end(); ++itr) {
    if ((*itr)->getRouterID() == router && (*itr)->hasAddress(ip)) {
      return *itr;
    }
  }
  throw FbossError("No interface with ip : ", ip);
}
Beispiel #21
0
AclEntryFields AclEntryFields::fromFollyDynamic(
    const folly::dynamic& aclEntryJson) {
  AclEntryFields aclEntry(AclEntryID(aclEntryJson[kId].asInt()));
  if (aclEntryJson.find(kSrcIp) != aclEntryJson.items().end()) {
    aclEntry.srcIp = IPAddress::createNetwork(
      aclEntryJson[kSrcIp].asString());
  }
  if (aclEntryJson.find(kDstIp) != aclEntryJson.items().end()) {
    aclEntry.dstIp = IPAddress::createNetwork(
      aclEntryJson[kDstIp].asString());
  }
  if (aclEntry.srcIp.first && aclEntry.dstIp.first &&
      aclEntry.srcIp.first.isV4() != aclEntry.dstIp.first.isV4()) {
    throw FbossError(
      "Unmatched ACL IP versions ",
      aclEntryJson[kSrcIp].asString(),
      " vs ",
      aclEntryJson[kDstIp].asString()
    );
  }
  if (aclEntryJson.find(kL4SrcPort) != aclEntryJson.items().end()) {
    aclEntry.l4SrcPort = aclEntryJson[kL4SrcPort].asInt();
  }
  if (aclEntryJson.find(kL4DstPort) != aclEntryJson.items().end()) {
    aclEntry.l4DstPort = aclEntryJson[kL4DstPort].asInt();
  }
  if (aclEntryJson.find(kProto) != aclEntryJson.items().end()) {
    aclEntry.proto = aclEntryJson[kProto].asInt();
  }
  if (aclEntryJson.find(kTcpFlags) != aclEntryJson.items().end()) {
    aclEntry.tcpFlags = aclEntryJson[kTcpFlags].asInt();
  }
  if (aclEntryJson.find(kTcpFlagsMask) != aclEntryJson.items().end()) {
    aclEntry.tcpFlagsMask = aclEntryJson[kTcpFlagsMask].asInt();
  }
  auto itr_action = cfg::_AclAction_NAMES_TO_VALUES.find(
    aclEntryJson[kAction].asString().c_str());
  if (itr_action == cfg::_AclAction_NAMES_TO_VALUES.end()) {
    throw FbossError(
      "Unsupported ACL action ", aclEntryJson[kAction].asString());
  }
  aclEntry.action = cfg::AclAction(itr_action->second);
  return aclEntry;
}
Beispiel #22
0
void PktCaptureManager::checkCaptureName(folly::StringPiece name) {
  // We use the capture name for the on-disk filename, so don't allow
  // directory separator characters or nul bytes.
  std::string invalidChars("\0/", 2);
  size_t idx = name.find_first_of(invalidChars);
  if (idx != std::string::npos) {
    throw FbossError("invalid capture name \"", name,
                     "\": invalid character at byte ", idx);
  }
}
Beispiel #23
0
void BcmIntfTable::deleteIntf(const std::shared_ptr<Interface>& intf) {
  auto iter = intfs_.find(intf->getID());
  if (iter == intfs_.end()) {
    throw FbossError("Failed to delete a non-existing interface ",
                     intf->getID());
  }
  auto bcmIfId = iter->second->getBcmIfId();
  intfs_.erase(iter);
  bcmIntfs_.erase(bcmIfId);
}
Beispiel #24
0
std::unique_ptr<BcmUnit> BcmAPI::initUnit(int deviceIndex) {
  auto unitObj = make_unique<BcmUnit>(deviceIndex);
  int unit = unitObj->getNumber();
  BcmUnit* expectedUnit{nullptr};
  if (!bcmUnits[unit].compare_exchange_strong(expectedUnit, unitObj.get(),
                                              std::memory_order_acq_rel)) {
    throw FbossError("a BcmUnit already exists for unit number ", unit);
  }
  return std::move(unitObj);
}
std::pair<ClientID, const RouteNextHopEntry *>
RouteNextHopsMulti::getBestEntry() const {
  auto entry = getEntryForClient(lowestAdminDistanceClientId_);
  if (entry) {
    return std::make_pair(lowestAdminDistanceClientId_, entry);
  } else {
    // Throw an exception if the map is empty. Shall not happen
    throw FbossError("Unexpected empty RouteNextHopsMulti");
  }
}
Beispiel #26
0
void TunManager::removeIntf(RouterID rid) {
  auto iter = intfs_.find(rid);
  if (iter == intfs_.end()) {
    throw FbossError("Cannot find to be delete interface for router ", rid);
  }
  auto& intf = iter->second;
  // remove the route table
  removeRouteTable(intf->getIfIndex(), intf->getRouterId());
  intf->setDelete();
  intfs_.erase(iter);
}
Beispiel #27
0
void TunIntf::addAddress(const IPAddress& addr, uint8_t mask) {
  auto ret = addrs_.emplace(addr, mask);
  if (!ret.second) {
    throw FbossError("Duplication interface address ", addr, "/",
                     static_cast<int>(mask), " for interface ", name_,
                     " @ index", ifIndex_);
  }
  VLOG(3) << "Added address " << addr.str() << "/"
          << static_cast<int>(mask) << " to interface " << name_
          << " @ index " << ifIndex_;
}
Beispiel #28
0
void BcmIntfTable::addIntf(const shared_ptr<Interface>& intf) {
  auto newIntf = unique_ptr<BcmIntf>(new BcmIntf(hw_));
  auto intfPtr = newIntf.get();
  auto ret = intfs_.insert(make_pair(intf->getID(), std::move(newIntf)));
  if (!ret.second) {
    throw FbossError("Adding an existing interface ", intf->getID());
  }
  intfPtr->program(intf);
  auto ret2 = bcmIntfs_.insert(make_pair(intfPtr->getBcmIfId(), intfPtr));
  CHECK_EQ(ret2.second, true);
}
Beispiel #29
0
void BcmUnit::attach() {
  if (attached_.load(std::memory_order_acquire)) {
    throw FbossError("unit ", unit_, " already initialized");
  }

  auto rv = opennsl_switch_event_register(unit_, switchEventCallback, this);
  bcmCheckError(rv, "unable to register switch event callback for unit ",
                unit_);

  attached_.store(true, std::memory_order_release);
}
Beispiel #30
0
void QsfpModule::setQsfpIdprom() {
uint8_t status[2];
  int offset;
  int length;
  int dataAddress;

  if (!present_) {
    throw FbossError("QSFP IDProm set failed as QSFP is not present");
  }

  // Check if the data is ready
  getQsfpFieldAddress(SffField::STATUS,
                      dataAddress, offset, length);
  getQsfpValue(dataAddress, offset, length, status);
  if (status[1] & (1 << 0)) {
    dirty_ = true;
    throw FbossError("QSFP IDProm failed as QSFP is not ready");
  }
  flatMem_ = status[1] & (1 << 2);
  dirty_ = false;
}