bool RoutingCompiler::cmpRules(const RoutingRule &r1, const RoutingRule &r2) { if (r1.getRDst()!=r2.getRDst()) return false; if (r1.getRGtw()!=r2.getRGtw()) return false; if (r1.getRItf()!=r2.getRItf()) return false; return true; }
string RoutingCompiler::debugPrintRule(Rule *r) { RoutingRule *rule = RoutingRule::cast(r); RuleElementRDst *dstrel = rule->getRDst(); RuleElementRItf *itfrel = rule->getRItf(); RuleElementRGtw *gtwrel = rule->getRGtw(); ostringstream str; // str << setw(70) << setfill('-') << "-"; string dst, itf, gtw; FWObject *obj = FWReference::getObject(itfrel->front()); itf = (obj) ? obj->getName() : "NULL"; obj = FWReference::getObject(gtwrel->front()); gtw = (obj) ? obj->getName() : "NULL"; int no = 0; FWObject::iterator i1 = dstrel->begin(); while ( i1!=dstrel->end()) { str << endl; dst = " "; if (i1 != dstrel->end()) { FWObject *o = FWReference::getObject(*i1); dst = (o) ? o->getName() : "NULL"; } int w = 0; if (no==0) { str << rule->getLabel(); w = rule->getLabel().length(); } str << setw(10-w) << setfill(' ') << " "; str << setw(18) << setfill(' ') << dst.c_str() << " "; str << setw(18) << setfill(' ') << itf.c_str() << " "; str << setw(18) << setfill(' ') << gtw.c_str() << " "; str << setw(18) << setfill(' ') << " "; ++no; if ( i1 != dstrel->end() ) ++i1; } return str.str(); }
bool RoutingCompiler::interfaceOrGateway::processNext() { RoutingRule *rule = getNext(); if (rule==NULL) return false; tmp_queue.push_back(rule); RuleElementRItf *itfrel = rule->getRItf(); RuleElementRGtw *gtwrel = rule->getRGtw(); if (!itfrel->isAny() && !gtwrel->isAny()) { compiler->abort(rule, "Use either gateway or interface in a routing rule " "but not both at the same time"); } return true; }
/* * Call this after converting to atomic rules by DST to be sure there * is just one object in DST. */ bool RoutingCompiler::sameDestinationDifferentGateways::processNext() { slurp(); if (tmp_queue.size()==0) return false; // map destination to gateway. std::map<string, string> dst_to_gw; std::map<string, string> dst_to_rule; for (deque<Rule*>::iterator k=tmp_queue.begin(); k!=tmp_queue.end(); ++k) { RoutingRule *rule = RoutingRule::cast( *k ); RuleElementRDst *dstrel = rule->getRDst(); Address *dst = Address::cast(FWReference::getObject(dstrel->front())); const InetAddr* dst_addr = dst->getAddressPtr(); const InetAddr* dst_netm = dst->getNetmaskPtr(); string key = dst_addr->toString() + "/" + dst_netm->toString(); // RuleElementRItf *itfrel = rule->getRItf(); // FWObject *itf = FWReference::cast(itfrel->front())->getPointer(); RuleElementRGtw *gtwrel = rule->getRGtw(); Address *gtw = Address::cast(FWReference::getObject(gtwrel->front())); const InetAddr* gtw_addr = gtw->getAddressPtr(); const InetAddr* gtw_netm = gtw->getNetmaskPtr(); string val = gtw_addr->toString() + "/" + gtw_netm->toString(); if (!dst_to_gw[key].empty() && dst_to_gw[key] != val) { compiler->abort( rule, "Rules " + dst_to_rule[key] + " and " + rule->getLabel() + " define routes to the same destination " + key + " via different gateways. This configuration is not supported" " for " + compiler->fw->getStr("host_OS")); } else { dst_to_gw[key] = val; dst_to_rule[key] = rule->getLabel(); } } return true; }
bool RoutingCompiler::classifyRoutingRules::processNext() { assert(compiler!=NULL); assert(prev_processor!=NULL); slurp(); if (tmp_queue.size()==0) return false; for (std::deque<libfwbuilder::Rule *>::iterator tmp_queue_it=tmp_queue.begin(); tmp_queue_it!=tmp_queue.end(); ++tmp_queue_it) { RoutingRule *rule = RoutingRule::cast( *tmp_queue_it); rule->setRuleType( RoutingRule::SinglePath); RuleElementRItf *itfrel=rule->getRItf(); FWObject *itf = FWReference::cast(itfrel->front())->getPointer(); RuleElementRGtw *gtwrel=rule->getRGtw(); FWObject *gtw = FWReference::cast(gtwrel->front())->getPointer(); string metric = rule->getMetricAsString(); string label = rule->getSortedDstIds(); ostringstream ostr; ostr << gtw->getId() << "_" << itf->getId(); string combiId = ostr.str(); if( label == "") compiler->abort( rule, "Place 'createSortedDstIdsLabel()' right before " "'classifyRoutingRules()' in the rule processor chain"); dest_it = rules_seen_so_far.find(label); if( dest_it != rules_seen_so_far.end()) { // a rule with the same destination was already seen //std::cout << "classifyRoutingRules:NO NEW DEST" << std::endl;/// gtwitf_it = dest_it->second.find(combiId); if( gtwitf_it == dest_it->second.end() ) { // ... this gateway and interface combination is new for this destination //std::cout << "classifyRoutingRules:NEW GTWITF" << std::endl;/// for( gtwitf_it = dest_it->second.begin(); gtwitf_it != dest_it->second.end(); gtwitf_it++) { if( gtwitf_it->second.first == metric) { // ... but has the same metric as another rule with this Dst => multipath or abort //std::cout << "classifyRoutingRules:SAME METRIC" << std::endl;/// if(true) { //TODO: if ( compiler->fw->getOptionsObject()->getBool ("equal_cost_multi_path") ) rule->setRuleType( RoutingRule::MultiPath); gtwitf_it->second.second->setRuleType( RoutingRule::MultiPath); //std::cout << "classifyRoutingRules:the rules " << rule->getLabel() << " and " << gtwitf_it->second.second->getLabel() << " were set to multipath." << std::endl;/// } } } dest_it->second[combiId] = pair< string, RoutingRule*>( metric, rule); } } else { // this destination is new //std::cout << "classifyRoutingRules:NEW DEST" << std::endl;/// map< string, pair< string, RoutingRule*> > gtw_itf_tmp; gtw_itf_tmp[combiId] = pair< string, RoutingRule*>( metric, rule); rules_seen_so_far[label] = gtw_itf_tmp; } } return true; }
bool RoutingCompiler::competingRules::processNext() { RoutingRule *rule = getNext(); if (rule==NULL) return false; RuleElementRItf *itfrel = rule->getRItf(); FWObject *itf = FWReference::cast(itfrel->front())->getPointer(); RuleElementRGtw *gtwrel = rule->getRGtw(); FWObject *gtw = FWReference::cast(gtwrel->front())->getPointer(); string metric = rule->getMetricAsString(); string label = rule->getSortedDstIds(); ostringstream ostr; ostr << gtw->getId() << "_" << itf->getId(); string combiId = ostr.str(); if( label == "") compiler->abort( rule, "Place 'createSortedDstIdsLabel()' before 'competingRules()' " "in the rule processor chain"); dest_it = rules_seen_so_far.find(label); if( dest_it != rules_seen_so_far.end()) { // a rule with the same destination was already seen ///std::cout << "NO NEW DEST" << std::endl; gtwitf_it = dest_it->second.find(combiId); if( gtwitf_it != dest_it->second.end() ) { // ... this gateway and interface combination were already // seen for this destination ///std::cout << "NO NEW GTWITF" << std::endl; if( gtwitf_it->second.first == metric) { // ... and same metric => rule already exists, skip ///std::cout << "SAME METRIC" << std::endl; string msg; msg = "Routing rules " + gtwitf_it->second.second + " and " + rule->getLabel() + " are identical, skipping the second one. " + "Delete one of them to avoid this warning"; compiler->warning(rule, msg.c_str()); } else { // ... but different metric => what metric should I use? => abort ///std::cout << "DIFFERENT METRIC" << std::endl; string msg; msg = "Routing rules " + gtwitf_it->second.second + " and " + rule->getLabel() + " are identical except for the metric, " + "please delete one of them"; compiler->abort(rule, msg.c_str()); } } else { // ... this gateway and interface combination is new for // this destination ///std::cout << "NEW GTWITF" << std::endl;/// if(false) { // TODO_lowPrio: if ( // !compiler->fw->getOptionsObject()->getBool // ("equal_cost_multi_path") ) ...If multipath is // turned off, perform this check. // iterate all gtwitf combis in the map // dest_it->second and search for the current metric // ... but has the same metric => what route should I // use for this destination? => abort string msg; msg = "Routing rules " + gtwitf_it->second.second + " and " + rule->getLabel() + " have the same destination and same metric," "but different gateway and interface combination. " "Set the metrics to different values or " "enable ECMP (Equal Cost MultiPath) routing"; compiler->abort( msg.c_str() ); } else { // ... and different metric OR equal_cost_multi_path enabled => OK tmp_queue.push_back(rule); } dest_it->second[combiId] = pair< string, string>( metric, rule->getLabel()); } } else { // this destination is new //std::cout << "NEW DEST" << std::endl; /// //ruleinfo tmpRuleInfo = { gtw->getStr("id") + itf->getStr("id"), metric, rule->getLabel()}; //rules_seen_so_far[label] = tmpRuleInfo; map< string, pair< string, string> > gtw_itf_tmp; gtw_itf_tmp[combiId] = pair< string, string>( metric, rule->getLabel()); rules_seen_so_far[label] = gtw_itf_tmp; tmp_queue.push_back(rule); } return true; }