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; }
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()); } }
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; }
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; }
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"); }
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); }
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; }
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...) }
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(); }
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; } }
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); }
BcmIntf* BcmIntfTable::getBcmIntf(InterfaceID id) const { auto ptr = getBcmIntfIf(id); if (ptr == nullptr) { throw FbossError("Cannot find interface ", id); } return ptr; }
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); }
InterfaceMap::Interfaces InterfaceMap::getInterfacesInVlan(VlanID vlan) const { auto interfaces = getInterfacesInVlanIf(vlan); if (interfaces.empty()) { throw FbossError("No interface in vlan : ", vlan); } return interfaces; }
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; }
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); }
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; }
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); } }
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); }
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"); } }
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); }
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_; }
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); }
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); }
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; }