Improvements to RtConfig IOS/JunOS

Daryl Collins daryl at htb.com.au
Mon Mar 4 06:10:04 UTC 2013


Hi,

Over the past year or so we've moved from using RtConfig only on Cisco IOS
to using it on JunOS & IOS XR as well.  I've written numerous patches to
RtConfig to solve various issues or implement/change features that we've
needed.   They are in production for us and work pretty well for our use
cases.

I don't pretend to be a programmer and I'm sure there are better ways to
implement the patches.  My hope is that by posting the various patches here
over the next while, that they will be picked up, developed further and
make it into a future release to be useful for others :)

All of the patches are against 5.0.0 but should apply fairly easily to
5.0.1  Here is the first batch:

*patch-01-ios-communitydelete.txt*
 - implements community.delete() for IOS

*patch-02-ios-peertemplates.txt*
 - change RtConfig from using peer groups to newer IOS peer templates

*patch-05-junos-ordering-and-duplicate-prefix-numbers.txt*
- fixed ordering issues:

     policy-statement as4802-private-in {
      term as4802-private-in-term-2 {
          from {
             as-path as-path-2;
             policy community-pol-2;
          }
          then {
             local-preference 250;
             community delete community-1;
    community community-32 members [4739:2000];    <<---- this should not
be here, should be outside of this policy-statement
             community add community-32;
             accept;
          }
       }
    }

- duplicated prefix-list’s - the name prefix-list-100 would be used once
for v4 prefixes, once for v6 prefixes, in junos this would cause one to
overwrite the other.

*patch-06-junos-acl-nos.txt*
- implements @RtConfig set junos_* the same way as IOS functionality works

*patch-08-junos-ipv6-prefix-length-range.txt*
- implements prefix-length-range for IPv6 on JunOS

*patch-11-junos-replace.txt*
- adds replace keywords to JunOS output so that you can use "load replace"
rather than "load merge" which isn't very predictable


Daryl
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.isc.org/pipermail/irrtoolset/attachments/20130304/33f9bd4d/attachment-0001.html>
-------------- next part --------------
--- src/rtconfig/f_cisco.cc.orig	2010-03-20 08:49:41.000000000 +1030
+++ src/rtconfig/f_cisco.cc	2013-03-04 16:19:30.000000000 +1030
@@ -917,6 +917,18 @@
 	    os << " set community ";
 	    printCommunityList(os, actn->args);
 	    os << " additive\n";
+         } else if (actn->rp_method == dctn_rp_community_delete) {
+            
+            // should be reimplemented to use printCommunities
+
+            int aclID = communityMgr.newID();
+            os << "!\nno ip community-list " << aclID << "\n";
+            os << "ip community-list " << aclID << " permit";
+	    printCommunityList(os, actn->args);
+            os << "\n";
+            os << " set comm-list ";
+            os << aclID;
+            os << " delete\n";
 	 } else
 	    UNIMPLEMENTED_METHOD;
 	 continue;
-------------- next part --------------
--- src/rtconfig/f_cisco.cc.orig	2010-07-20 10:08:33.119388292 +0930
+++ src/rtconfig/f_cisco.cc	2010-07-20 13:06:04.576387942 +0930
@@ -1115,12 +1118,17 @@ bool CiscoConfig::printNeighbor(int impo
    // create bgp process 
    cout << "!\nrouter bgp " << asno << "\n!\n";
 
-   if (peerGroup)
-     cout << " neighbor "   << neighbor << " peer-group\n";
-   else 
+   if (peerGroup) {
+     cout << "template peer-policy " << neighbor <<"\n";
+     if (routeMapGenerated)
+       cout << " route-map " << mapName << " " << direction << "\n";
+     cout << " remove-private-as\n";
+     cout << "exit-peer-policy\n!\n";
+   } else  {
      cout << " neighbor "   << neighbor << " remote-as " << peerAS << "\n";
+   }
 
-   if (afi_activate && !peerGroup) {
+   if (afi_activate ) {
      if (strcmp(filter_afi->name(),"ipv6") == 0) {
        cout << " address-family " << "ipv4" << endl;
        cout << indent <<" no neighbor " << neighbor << " activate\n"; 
@@ -1148,7 +1156,7 @@ bool CiscoConfig::printNeighbor(int impo
      // ought to handle afi any too, but that's not just done by naming it here
    }
 
-   if (routeMapGenerated) 
+   if (routeMapGenerated && !peerGroup) 
       cout << indent << " neighbor " << neighbor 
 	   << " route-map " << mapName << " " << direction << "\n";
    
@@ -1710,40 +1718,38 @@ void CiscoConfig::importGroup(ASt asno, 
    if (prngSet) {
      AutNumPeeringIterator aut_itr(autnum);
 
-     for (AttrIterator<AttrPeering> itr(prngSet, "peering"); itr; itr++)
-       if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
-            && typeid(*itr()->peering->peerASes) == typeid(FilterASNO))
-         cout << " neighbor " << *itr()->peering->peerRtrs  
-              << " remote-as " << *itr()->peering->peerASes << endl;
-     for (AttrIterator<AttrPeering> itr(prngSet, "mp-peering"); itr; itr++)
-       if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
-            && typeid(*itr()->peering->peerASes) == typeid(FilterASNO))
-         cout << " neighbor " << *itr()->peering->peerRtrs  
-              << " remote-as " << *itr()->peering->peerASes << endl;
-
      for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
        bool afi_activate = false;
        ItemAFI *iafi = (ItemAFI *)afi;
        if (!iafi->is_default())
          afi_activate = true;
        const char *indent = (afi_activate) ? " " : "";
-       if (afi_activate)
-         cout << " address-family " << iafi->name_afi() << " " << iafi->name_safi() << endl;
 
+       cout << " address-family " << iafi->name_afi() << " " << iafi->name_safi() << endl;
        for (AttrIterator<AttrPeering> itr(prngSet, "peering"); itr; itr++) {
          if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
+              && typeid(*itr()->peering->peerASes) == typeid(FilterASNO))
+           cout << " neighbor " << *itr()->peering->peerRtrs  
+                << " remote-as " << *itr()->peering->peerASes << endl;
+         if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
               && typeid(*itr()->peering->peerASes) == typeid(FilterASNO)) {
            if (afi_activate)
              cout << indent << " neighbor " << *itr()->peering->peerRtrs << " activate\n";
-           cout << indent << " neighbor " << *itr()->peering->peerRtrs  << " peer-group " << pset << "\n";
+           cout << indent << " neighbor " << *itr()->peering->peerRtrs  << " inherit peer-policy " << pset << "\n";
          }
        }
+
+       cout << " address-family ipv6 unicast" << endl;
        for (AttrIterator<AttrPeering> itr(prngSet, "mp-peering"); itr; itr++) {
          if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
+              && typeid(*itr()->peering->peerASes) == typeid(FilterASNO))
+           cout << " neighbor " << *itr()->peering->peerRtrs  
+                << " remote-as " << *itr()->peering->peerASes << endl;
+         if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
               && typeid(*itr()->peering->peerASes) == typeid(FilterASNO)) {
            if (afi_activate)
              cout << indent << " neighbor " << *itr()->peering->peerRtrs << " activate\n";
-           cout << indent << " neighbor " << *itr()->peering->peerRtrs  << " peer-group " << pset << "\n";
+           cout << indent << " neighbor " << *itr()->peering->peerRtrs  << " inherit peer-policy " << pset << "\n";
          }
        }
 
@@ -1806,40 +1812,40 @@ void CiscoConfig::exportGroup(ASt asno, 
    if (prngSet) {
      AutNumPeeringIterator aut_itr(autnum);
 
-     for (AttrIterator<AttrPeering> itr(prngSet, "peering"); itr; itr++)
-       if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
-            && typeid(*itr()->peering->peerASes) == typeid(FilterASNO))
-         cout << " neighbor " << *itr()->peering->peerRtrs  
-              << " remote-as " << *itr()->peering->peerASes << endl;
-     for (AttrIterator<AttrPeering> itr(prngSet, "mp-peering"); itr; itr++)
-       if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
-            && typeid(*itr()->peering->peerASes) == typeid(FilterASNO))
-         cout << " neighbor " << *itr()->peering->peerRtrs  
-              << " remote-as " << *itr()->peering->peerASes << endl;
-
      for (Item *afi = afi_list->head(); afi; afi = afi_list->next(afi)) {
        bool afi_activate = false;
        ItemAFI *iafi = (ItemAFI *)afi;
        if (!iafi->is_default())
          afi_activate = true;
        const char *indent = (afi_activate) ? " " : "";
-       if (afi_activate)
-         cout << " address-family " << iafi->name_afi() << " " << iafi->name_safi() << endl;
 
+       cout << " address-family " << iafi->name_afi() << " " << iafi->name_safi() << endl;
        for (AttrIterator<AttrPeering> itr(prngSet, "peering"); itr; itr++) {
          if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
+            && typeid(*itr()->peering->peerASes) == typeid(FilterASNO)) {
+           cout << " neighbor " << *itr()->peering->peerRtrs  
+                << " remote-as " << *itr()->peering->peerASes << endl;
+         }
+         if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
               && typeid(*itr()->peering->peerASes) == typeid(FilterASNO)) {
            if (afi_activate)
              cout << indent << " neighbor " << *itr()->peering->peerRtrs << " activate\n";
-           cout << indent << " neighbor " << *itr()->peering->peerRtrs  << " peer-group " << pset << "\n";
+           cout << indent << " neighbor " << *itr()->peering->peerRtrs  << " inherit peer-policy " << pset << "\n";
          }
        }
+
+       cout << " address-family ipv6 unicast" << endl;
        for (AttrIterator<AttrPeering> itr(prngSet, "mp-peering"); itr; itr++) {
          if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
+            && typeid(*itr()->peering->peerASes) == typeid(FilterASNO)) {
+           cout << " neighbor " << *itr()->peering->peerRtrs  
+                << " remote-as " << *itr()->peering->peerASes << endl;
+         }
+         if (typeid(*itr()->peering->peerRtrs) == typeid(FilterRouter)  
               && typeid(*itr()->peering->peerASes) == typeid(FilterASNO)) {
            if (afi_activate)
              cout << indent << " neighbor " << *itr()->peering->peerRtrs << " activate\n";
-           cout << indent << " neighbor " << *itr()->peering->peerRtrs  << " peer-group " << pset << "\n";
+           cout << indent << " neighbor " << *itr()->peering->peerRtrs  << " inherit peer-policy " << pset << "\n";
          }
        }
 
-------------- next part --------------
--- src/rtconfig/f_junos.cc.orig	2010-03-20 08:49:41.000000000 +1030
+++ src/rtconfig/f_junos.cc	2012-10-22 09:25:38.000000000 +1030
@@ -107,7 +107,10 @@
 		return result;
 
 	result = ipv6prefixMgr.add(nets);
-	int aclID = ipv6prefixMgr.newID();
+
+	// also increment prefixMgr id to avoid v4 v's v6 duplicated policies
+	int aclID = prefixMgr.newID();
+	aclID = ipv6prefixMgr.newID();
 	result->add(aclID, aclID);
 
 	bool allow_flag = true;
@@ -161,7 +164,10 @@
       return result;
 
    result = prefixMgr.add(nets);
-   int aclID = prefixMgr.newID();
+
+   // also increment ipv6prefixMgr id to avoid v4 v's v6 duplicated policies
+   int aclID = ipv6prefixMgr.newID();
+   aclID = prefixMgr.newID();
    result->add(aclID, aclID);
 
    bool allow_flag = true;
@@ -616,7 +622,7 @@
    return result;
 }
 
-void JunosConfig::printActions(ostream &os, PolicyActionList *actions, ItemAFI *afi) {
+void JunosConfig::printActions(ostream &os, PolicyActionList *actions, ItemAFI *afi, ostringstream &lastCout) {
 #define UNIMPLEMENTED_METHOD \
    cerr << "Warning: unimplemented method " \
 	<< actn->rp_attr->name << "." << actn->rp_method->name << endl
@@ -676,19 +682,19 @@
       if (actn->rp_attr == dctn_rp_community) {
 	 if (actn->rp_method == dctn_rp_community_setop) {
 	    os << "            community set community-" 
-	       << printCommunityList(os, (ItemList *) actn->args->head())
+	       << printCommunityList(lastCout, (ItemList *) actn->args->head())
 	       << ";\n";
 	 } else if (actn->rp_method == dctn_rp_community_appendop) {
 	    os << "            community add community-"
-	       << printCommunityList(os, (ItemList *) actn->args->head())
+	       << printCommunityList(lastCout, (ItemList *) actn->args->head())
 	       << ";\n";
 	 } else if (actn->rp_method == dctn_rp_community_append) {
 	    os << "            community add community-"
-	       << printCommunityList(os, actn->args)
+	       << printCommunityList(lastCout, actn->args)
 	       << ";\n";
 	 } else if (actn->rp_method == dctn_rp_community_delete) {
 	    os << "            community delete community-"
-	       << printCommunityList(os, actn->args)
+	       << printCommunityList(lastCout, actn->args)
 	       << ";\n";
 	 } else
 	    UNIMPLEMENTED_METHOD;
@@ -747,6 +753,7 @@
 		       int import_flag, ItemAFI *afi) {
    int last = 0;
    static ListOf2Ints empty_list(1);
+   ostringstream lastCout;
 
    Debug(Channel(DBG_RTC_JUNOS) << "# ne: " << *ne << "\n");
 
@@ -809,12 +816,13 @@
 
 		  cout << "         }\n"
 		       << "         then {\n";
-		  JunosConfig::printActions(cout, actn, afi);
+		  JunosConfig::printActions(cout, actn, afi, lastCout);
 		  cout << "         }\n";
 		  cout << "      }\n";
 	       }
 	       cout << "   }\n\n";
 	    }
+            cout << lastCout.str() << "\n";
 	 }
       }
    }
--- src/rtconfig/f_junos.hh	2010-03-20 08:49:41.000000000 +1030
+++ src/rtconfig/f_junos.hh	2012-10-22 09:26:59.000000000 +1030
@@ -113,7 +113,7 @@
    inline void  printCommunity(std::ostream &os, unsigned int i);
    int          printCommunityList(std::ostream &os, ItemList *args);
    int          printCommunitySet(std::ostream &os, CommunitySet *set, bool exact);
-   void         printActions(std::ostream &os, PolicyActionList *action, ItemAFI *afi);
+   void         printActions(std::ostream &os, PolicyActionList *action, ItemAFI *afi,std::ostringstream &lastCout);
    void         printMartians();
    int          print(NormalExpression *ne, PolicyActionList *actn, int import_flag, ItemAFI *afi);
    int          printDeclarations(NormalExpression *ne, PolicyActionList *actn, int import_flag);
-------------- next part --------------
--- src/rtconfig/f_junos.hh.orig	2012-10-29 11:27:44.000000000 +1030
+++ src/rtconfig/f_junos.hh	2012-10-29 11:26:49.000000000 +1030
@@ -147,5 +147,6 @@
 extern AccessListManager<SetOfIPv6Prefix>   ipv6prefixMgr;
 extern AccessListManager<SetOfPrefix>       pktFilterMgr;
 extern AccessListManager<FilterOfCommunity> communityMgr;
+extern AccessListManager<CommunitySet>      communityMgr2;
 
 #endif   // F_JUNOS_H
--- src/rtconfig/command.l.orig	2010-03-20 08:49:41.000000000 +1030
+++ src/rtconfig/command.l	2012-10-29 11:22:24.000000000 +1030
@@ -110,9 +110,14 @@
 "cisco_map_first_no",      KW_CISCO_MAP_START,
 "cisco_access_list_no",    KW_CISCO_ACCESS_LIST_NO,
 "cisco_prefix_acl_no",     KW_CISCO_PREFIX_ACL_NO,
+"junos_prefix_acl_no",     KW_JUNOS_PREFIX_ACL_NO,
 "cisco_aspath_acl_no",     KW_CISCO_ASPATH_ACL_NO,
+"junos_aspath_acl_no",     KW_JUNOS_ASPATH_ACL_NO,
 "cisco_pktfilter_acl_no",  KW_CISCO_PKTFILTER_ACL_NO,
+"junos_pktfilter_acl_no",  KW_JUNOS_PKTFILTER_ACL_NO,
 "cisco_community_acl_no",  KW_CISCO_COMMUNITY_ACL_NO,
+"junos_community_acl_no",  KW_JUNOS_COMMUNITY_ACL_NO,
+"junos_community_set_no",  KW_JUNOS_COMMUNITY_SET_NO,
 "cisco_max_preference",    KW_PREFERENCECEILING,
 "sources",                 KW_SOURCE,
 NULL,        -1
--- src/rtconfig/command.y.orig	2010-03-20 08:49:41.000000000 +1030
+++ src/rtconfig/command.y	2012-10-29 11:25:39.000000000 +1030
@@ -115,10 +115,16 @@
 %token <val> KW_CISCO_MAP_NAME
 %token <val> KW_JUNOS_POLICY_NAME
 %token <val> KW_CISCO_PREFIX_ACL_NO
+%token <val> KW_JUNOS_PREFIX_ACL_NO
 %token <val> KW_CISCO_ASPATH_ACL_NO
+%token <val> KW_JUNOS_ASPATH_ACL_NO
 %token <val> KW_CISCO_PKTFILTER_ACL_NO
+%token <val> KW_JUNOS_PKTFILTER_ACL_NO
 %token <val> KW_CISCO_COMMUNITY_ACL_NO
+%token <val> KW_JUNOS_COMMUNITY_ACL_NO
+%token <val> KW_JUNOS_COMMUNITY_SET_NO
 %token <val> KW_CISCO_ACCESS_LIST_NO
+%token <val> KW_JUNOS_ACCESS_LIST_NO
 %token <val> KW_SOURCE
 %token <val> KW_PREFERENCECEILING
 %token <val> KW_CISCO_MAX_PREFERENCE
@@ -173,6 +179,7 @@
 | cisco_map_inc_line
 | cisco_map_start_line
 | cisco_access_list_no_line
+| junos_access_list_no_line
 | preferenceCeiling_line
 | source_line
 ;
@@ -362,7 +369,7 @@
 | KW_SET KW_CISCO_COMMUNITY_ACL_NO '=' TKN_INT {
    if ($4 > 0)
       communityMgr.setNextID($4);
-   Trace(TR_INPUT) << "RtConfig: cisco_pktfilter_access_list_no '"
+   Trace(TR_INPUT) << "RtConfig: cisco_community_access_list_no '"
 		   << $4 << "'" << std::endl;
 }
 | KW_SET KW_CISCO_ACCESS_LIST_NO '=' TKN_INT {
@@ -374,7 +381,50 @@
       ipv6prefixMgr.setNextID($4);
       ipv6pktFilterMgr.setNextID($4);
    }
-   Trace(TR_INPUT) << "RtConfig: cisco_pktfilter_access_list_no '"
+   Trace(TR_INPUT) << "RtConfig: cisco_access_list_no '"
+		   << $4 << "'" << std::endl;
+}
+;
+junos_access_list_no_line: KW_SET KW_JUNOS_PREFIX_ACL_NO '=' TKN_INT {
+   if ($4 > 0)
+      prefixMgr.setNextID($4);
+   Trace(TR_INPUT) << "RtConfig: junos_prefix_access_list_no '"
+		   << $4 << "'" << std::endl;
+}
+| KW_SET KW_JUNOS_ASPATH_ACL_NO '=' TKN_INT {
+   if ($4 > 0)
+      aspathMgr.setNextID($4);
+   Trace(TR_INPUT) << "RtConfig: junos_aspath_access_list_no '"
+		   << $4 << "'" << std::endl;
+}
+| KW_SET KW_JUNOS_PKTFILTER_ACL_NO '=' TKN_INT {
+   if ($4 > 0)
+      pktFilterMgr.setNextID($4);
+   Trace(TR_INPUT) << "RtConfig: junos_pktfilter_access_list_no '"
+		   << $4 << "'" << std::endl;
+}
+| KW_SET KW_JUNOS_COMMUNITY_ACL_NO '=' TKN_INT {
+   if ($4 > 0)
+      communityMgr.setNextID($4);
+   Trace(TR_INPUT) << "RtConfig: junos_community_access_list_no '"
+		   << $4 << "'" << std::endl;
+}
+| KW_SET KW_JUNOS_COMMUNITY_SET_NO '=' TKN_INT {
+   if ($4 > 0)
+      communityMgr2.setNextID($4);
+   Trace(TR_INPUT) << "RtConfig: junos_community_set_no '"
+		   << $4 << "'" << std::endl;
+}
+| KW_SET KW_JUNOS_ACCESS_LIST_NO '=' TKN_INT {
+   if ($4 > 0) {
+      communityMgr.setNextID($4);
+      pktFilterMgr.setNextID($4);
+      aspathMgr.setNextID($4);
+      prefixMgr.setNextID($4);
+      ipv6prefixMgr.setNextID($4);
+      ipv6pktFilterMgr.setNextID($4);
+   }
+   Trace(TR_INPUT) << "RtConfig: junos_pktfilter_access_list_no '"
 		   << $4 << "'" << std::endl;
 }
 ;
-------------- next part --------------
--- src/rtconfig/f_junos.cc.orig	2013-01-17 09:47:52.000000000 +1030
+++ src/rtconfig/f_junos.cc	2013-01-17 10:01:24.000000000 +1030
@@ -133,12 +133,36 @@
           << "\n      }\n   }\n\n";
    } else {
      cout << "         from {\n";
+   }
+
+   if (compressAcls) {
+      for (bool ok = itr.first(addr, leng, start, end);
+       ok;
+       ok = itr.next(addr, leng, start, end)) {
 
-     for (bool ok = itr.first(addr, leng, start, end); ok; ok = itr.next(addr, leng, start, end)) {
        cout << "            route-filter ";
        cout << ipv62hex(&addr, buffer) << "/" << leng;
-       cout  << " exact" << returnPermitOrDeny(allow_flag) << "\n";
+        if (start != leng) {
+          if (end != leng || start < leng)
+            cout << " prefix-length-range /" << start << "-/" << end;
+          else
+            cout << " prefix-length-range /" << start << "-/" << start;
+        } else {
+          if (end != leng) cout << " upto /" << end;
+          else cout << " exact";
+        }
+	 
+       cout  << returnPermitOrDeny(allow_flag) << "\n";
+      }
+
+   } else {
+       for (bool ok = itr.first(addr, leng, start, end); ok; ok = itr.next(addr, leng, start, end)) {
+         cout << "            route-filter ";
+         cout << ipv62hex(&addr, buffer) << "/" << leng;
+         cout  << " exact" << returnPermitOrDeny(allow_flag) << "\n";
+       }
      }
+   
 
      cout << "         }\n"
           << "      }\n"
@@ -149,7 +173,6 @@
 
      cout << "      }\n"
           << "   }\n\n";
-   }
    
    return result;
 }
-------------- next part --------------
--- src/rtconfig/f_junos.cc.orig	2013-02-18 15:25:05.000000000 +1030
+++ src/rtconfig/f_junos.cc		2013-02-18 15:26:58.000000000 +1030
@@ -117,7 +117,7 @@
 	if (nets.negated())
 		allow_flag = false;
 
-   cout << "   policy-statement prefix-list-" << aclID << " {\n"
+   cout << "   replace: policy-statement prefix-list-" << aclID << " {\n"
     << "      term prefixes {\n";
 
    IPv6RadixSet::SortedPrefixRangeIterator itr(&nets.members);
@@ -201,7 +201,7 @@
 
    char buffer[64];
 
-   cout << "   policy-statement prefix-list-" << aclID << " {\n"
+   cout << "   replace: policy-statement prefix-list-" << aclID << " {\n"
        << "      term prefixes {\n";
 
    if (nets.members.isEmpty()) {
@@ -419,7 +419,7 @@
    regexp_nf::RegexpConjunct *rc;
    regexp_nf::RegexpConjunct::ReInt *ri;
 
-   cout << "   as-path as-path-" << aclID << " \"";
+   cout << "   replace: as-path as-path-" << aclID << " \"";
 
    if (path.re->rclist.size() == 1) {
       rc = path.re->rclist.head(); 
@@ -493,7 +493,7 @@
    int id = communityMgr2.newID();
    result->add(id, id);
 
-   os << "   community community-" << id << " members ";
+   os << "   replace: community community-" << id << " members ";
    if (exact)
       os << "^";
    else
@@ -531,7 +531,7 @@
    int aclID = communityMgr.newID();
    result->add(aclID, aclID);
 
-   lastCout << "   policy-statement community-pol-" << aclID << " {\n";
+   lastCout << "   replace: policy-statement community-pol-" << aclID << " {\n";
 
    // now print the communities
    // first print the conjuncts which are only positives
@@ -821,6 +821,7 @@
       if (printRouteMap) {
 	 for (asp = aspath_acls->head(); asp; asp = aspath_acls->next(asp)) {
 	    for (cmp = comm_acls->head(); cmp; cmp = comm_acls->next(cmp)) {
+               if (routeMapID == 1) cout << "   replace: ";
 	       cout << "   policy-statement " << mapName << " {\n";
 	       for (prp = prfx_acls->head(); prp; prp =prfx_acls->next(prp)) {
 		  cout << "      term " << mapName << "-term-" << routeMapID << " {\n"


More information about the irrtoolset mailing list