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; }
shared_ptr<Port> ThriftConfigApplier::updatePort(const shared_ptr<Port>& orig, const cfg::Port* cfg) { CHECK_EQ(orig->getID(), cfg->logicalID); auto vlans = portVlans_[orig->getID()]; if (cfg->state == orig->getState() && VlanID(cfg->ingressVlan) == orig->getIngressVlan() && vlans == orig->getVlans() && cfg->speed == orig->getSpeed() && (cfg->name.empty() || cfg->name == orig->getName())) { return nullptr; } auto newPort = orig->clone(); newPort->setState(cfg->state); newPort->setIngressVlan(VlanID(cfg->ingressVlan)); newPort->setVlans(vlans); newPort->setSpeed(cfg->speed); // If the port name isn't set in the config (it's optional), // leave it with the default value. if (!cfg->name.empty()) { newPort->setName(cfg->name); } return newPort; }
BcmRxPacket::BcmRxPacket(const opennsl_pkt_t* pkt) : unit_(pkt->unit) { // The BCM RX code always uses a single buffer. // As long as there is just a single buffer, we don't need to allocate // a separate array of opennsl_pkt_blk_t objects. CHECK_EQ(pkt->blk_count, 1); CHECK_EQ(pkt->pkt_data, &pkt->_pkt_data); // The BCM RX code always uses a single buffer. // Therefore we don't bother checking to see if we need to create a chain of // IOBufs rather than just one. CHECK_EQ(pkt->blk_count, 1); // The packet contains Ethernet FCS (frame check sequence) at the end before // interpacket gap, which we are not interested in. uint32_t length = std::max(pkt->pkt_len - 4, 0); buf_ = IOBuf::takeOwnership( pkt->pkt_data->data, // void* buf length, freeRxBuf, // FreeFunction freeFn reinterpret_cast<void*>(unit_)); // void* userData // TODO(aeckert): fix sdk bug where the src_port is a signed 8-bit // int. This causes issues when the logical port numbers exceed // 127. For now we work around the issue by casting to an 8-bit // unsigned port id, but we should fix this in the sdk. srcPort_ = PortID(static_cast<uint8_t>(pkt->src_port)); srcVlan_ = VlanID(pkt->vlan); len_ = length; }
VlanFields VlanFields::fromFollyDynamic(const folly::dynamic& vlanJson) { VlanFields vlan(VlanID(vlanJson[kVlanId].asInt()), vlanJson[kVlanName].asString().toStdString()); vlan.mtu = vlanJson[kVlanMtu].asInt(); vlan.dhcpV4Relay = folly::IPAddressV4( vlanJson[kDhcpV4Relay].stringPiece()); vlan.dhcpV6Relay = folly::IPAddressV6( vlanJson[kDhcpV6Relay].stringPiece()); for (const auto& o: vlanJson[kDhcpV4RelayOverrides].items()) { vlan.dhcpRelayOverridesV4[MacAddress(o.first.asString().toStdString())] = folly::IPAddressV4(o.second.stringPiece()); } for (const auto& o: vlanJson[kDhcpV6RelayOverrides].items()) { vlan.dhcpRelayOverridesV6[MacAddress(o.first.asString().toStdString())] = folly::IPAddressV6(o.second.stringPiece()); } for (const auto& portInfo: vlanJson[kMemberPorts].items()) { vlan.ports.emplace(PortID(to<uint16_t>(portInfo.first.asString())), PortInfo::fromFollyDynamic(portInfo.second)); } vlan.arpTable = ArpTable::fromFollyDynamic(vlanJson[kArpTable]); vlan.ndpTable = NdpTable::fromFollyDynamic(vlanJson[kNdpTable]); vlan.arpResponseTable = ArpResponseTable::fromFollyDynamic( vlanJson[kArpResponseTable]); vlan.ndpResponseTable = NdpResponseTable::fromFollyDynamic( vlanJson[kNdpResponseTable]); return vlan; }
shared_ptr<Vlan> ThriftConfigApplier::createVlan(const cfg::Vlan* config) { const auto& ports = vlanPorts_[VlanID(config->id)]; auto vlan = make_shared<Vlan>(config, ports); updateNeighborResponseTables(vlan.get(), config); updateDhcpOverrides(vlan.get(), config); return vlan; }
PortFields PortFields::fromFollyDynamic(const folly::dynamic& portJson) { PortFields port(PortID(portJson[kPortId].asInt()), portJson[kPortName].asString().toStdString()); auto itr_state = cfg::_PortState_NAMES_TO_VALUES.find( portJson[kPortState].asString().c_str()); CHECK(itr_state != cfg::_PortState_NAMES_TO_VALUES.end()); port.state = cfg::PortState(itr_state->second); port.ingressVlan = VlanID(portJson[kIngressVlan].asInt()); auto itr_speed = cfg::_PortSpeed_NAMES_TO_VALUES.find( portJson[kPortSpeed].asString().c_str()); CHECK(itr_speed != cfg::_PortSpeed_NAMES_TO_VALUES.end()); port.speed = cfg::PortSpeed(itr_speed->second); for (const auto& vlanInfo: portJson[kVlanMemberships].items()) { port.vlans.emplace(VlanID(to<uint32_t>(vlanInfo.first.asString())), VlanInfo::fromFollyDynamic(vlanInfo.second)); } return port; }
SwitchStateFields SwitchStateFields::fromFollyDynamic(const folly::dynamic& swJson) { SwitchStateFields switchState; switchState.interfaces = InterfaceMap::fromFollyDynamic( swJson[kInterfaces]); switchState.ports = PortMap::fromFollyDynamic(swJson[kPorts]); switchState.vlans = VlanMap::fromFollyDynamic(swJson[kVlans]); switchState.routeTables = RouteTableMap::fromFollyDynamic( swJson[kRouteTables]); switchState.acls = AclMap::fromFollyDynamic(swJson[kAcls]); switchState.defaultVlan = VlanID(swJson[kDefaultVlan].asInt()); //TODO verify that created state here is internally consistent t4155406 return switchState; }
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; }
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; }
BcmRxPacket::BcmRxPacket(const opennsl_pkt_t* pkt) : unit_(pkt->unit) { // The BCM RX code always uses a single buffer. // As long as there is just a single buffer, we don't need to allocate // a separate array of opennsl_pkt_blk_t objects. CHECK_EQ(pkt->blk_count, 1); CHECK_EQ(pkt->pkt_data, &pkt->_pkt_data); // The BCM RX code always uses a single buffer. // Therefore we don't bother checking to see if we need to create a chain of // IOBufs rather than just one. CHECK_EQ(pkt->blk_count, 1); buf_ = IOBuf::takeOwnership( pkt->pkt_data->data, // void* buf pkt->pkt_len, // uint32_t capacity freeRxBuf, // FreeFunction freeFn reinterpret_cast<void*>(unit_)); // void* userData srcPort_ = PortID(pkt->src_port); srcVlan_ = VlanID(pkt->vlan); len_ = pkt->pkt_len; }
BcmRxPacket::BcmRxPacket(const opennsl_pkt_t* pkt) : unit_(pkt->unit) { // The BCM RX code always uses a single buffer. // As long as there is just a single buffer, we don't need to allocate // a separate array of opennsl_pkt_blk_t objects. CHECK_EQ(pkt->blk_count, 1); CHECK_EQ(pkt->pkt_data, &pkt->_pkt_data); // The packet contains Ethernet FCS (frame check sequence) at the end before // interpacket gap, which we are not interested in. uint32_t length = std::max(pkt->pkt_len - 4, 0); buf_ = IOBuf::takeOwnership( pkt->pkt_data->data, // void* buf length, freeRxBuf, // FreeFunction freeFn reinterpret_cast<void*>(unit_)); // void* userData srcPort_ = PortID(pkt->src_port); srcVlan_ = VlanID(pkt->vlan); len_ = length; }
SwitchStateFields SwitchStateFields::fromFollyDynamic(const folly::dynamic& swJson) { SwitchStateFields switchState; switchState.interfaces = InterfaceMap::fromFollyDynamic( swJson[kInterfaces]); switchState.ports = PortMap::fromFollyDynamic(swJson[kPorts]); switchState.vlans = VlanMap::fromFollyDynamic(swJson[kVlans]); switchState.routeTables = RouteTableMap::fromFollyDynamic( swJson[kRouteTables]); switchState.acls = AclMap::fromFollyDynamic(swJson[kAcls]); if (swJson.count(kSflowCollectors) > 0) { switchState.sFlowCollectors = SflowCollectorMap::fromFollyDynamic( swJson[kSflowCollectors]); } switchState.defaultVlan = VlanID(swJson[kDefaultVlan].asInt()); if (swJson.find(kControlPlane) != swJson.items().end()) { switchState.controlPlane = ControlPlane::fromFollyDynamic( swJson[kControlPlane]); } //TODO verify that created state here is internally consistent t4155406 return switchState; }
uint32_t NeighborUpdater::flushEntry(VlanID vlan, IPAddress ip) { // clone caches_ so we don't need to hold the lock while flushing entries boost::container::flat_map<VlanID, std::shared_ptr<NeighborCaches>> caches; { std::lock_guard<std::mutex> g(cachesMutex_); caches = caches_; } uint32_t count{0}; if (vlan == VlanID(0)) { for (auto it = caches.begin(); it != caches.end(); ++it) { if (flushEntryImpl(it->first, ip)) { ++count; } } } else { if (flushEntryImpl(vlan, ip)) { ++count; } } return count; }
Vlan::Vlan(const cfg::Vlan* config, uint32_t mtu, MemberPorts ports) : NodeBaseT(VlanID(config->id), config->name, mtu, (config->__isset.dhcpRelayAddressV4 ? IPAddressV4(config->dhcpRelayAddressV4) : IPAddressV4()), (config->__isset.dhcpRelayAddressV6 ? IPAddressV6(config->dhcpRelayAddressV6) : IPAddressV6()), std::move(ports)) { DhcpV4OverrideMap map4; for (const auto& o: config->dhcpRelayOverridesV4) { map4[MacAddress(o.first)] = folly::IPAddressV4(o.second); } setDhcpV4RelayOverrides(map4); DhcpV6OverrideMap map6; for (const auto& o: config->dhcpRelayOverridesV6) { map6[MacAddress(o.first)] = folly::IPAddressV6(o.second); } setDhcpV6RelayOverrides(map6); }