Browse Source

2016-02-05 Technik/Routing/IGP-Kopplung/bird.conf (Prototypimplentierung zum Text Fußgängerzonenproblem)

Ignore-this: a737c98bf0e95c8b10c4d817f33d0723
altlast 9 years ago
parent
commit
0275f5514e
1 changed files with 411 additions and 0 deletions
  1. 411 0
      Technik/Routing/IGP-Kopplung/bird.conf

+ 411 - 0
Technik/Routing/IGP-Kopplung/bird.conf

@@ -0,0 +1,411 @@
+log syslog all;
+
+/* Definitionen fuer die Bitarithmetik der Schleifenverhinderungsmechanik */
+
+define OSPF_tag_sourcebits = 5; /* ld(32) */
+define OSPF_tag_pathbits = 32 - OSPF_tag_sourcebits;
+define OSPF_tag_pathvalue_div = 32 ; /* 2 ^ OSPF_tag_sourcebits */
+
+function fn_tag_to_source (int tagbits) {
+	return tagbits - ((tagbits / OSPF_tag_pathvalue_div) * OSPF_tag_pathvalue_div);
+}
+
+function fn_tag_to_path (int tagbits) {
+	return tagbits / OSPF_tag_pathvalue_div;
+}
+
+function fn_power_of_2 (int n) {
+	# awk 'BEGIN { for ( i=0 ; i < 32 ; i++ ) print "\t\t" i ": return " 2^i ";" }'
+	case n {
+		0: return 1;
+		1: return 2;
+		2: return 4;
+		3: return 8;
+		4: return 16;
+		5: return 32;
+		6: return 64;
+		7: return 128;
+		8: return 256;
+		9: return 512;
+		10: return 1024;
+		11: return 2048;
+		12: return 4096;
+		13: return 8192;
+		14: return 16384;
+		15: return 32768;
+		16: return 65536;
+		17: return 131072;
+		18: return 262144;
+		19: return 524288;
+		20: return 1048576;
+		21: return 2097152;
+		22: return 4194304;
+		23: return 8388608;
+		24: return 16777216;
+		25: return 33554432;
+		26: return 67108864;
+		27: return 134217728;
+		28: return 268435456;
+		29: return 536870912;
+		30: return 1073741824;
+		31: return 2147483648;
+		else: return 0;
+		}
+}
+
+function fn_instance_to_tagbit (int inst) {
+	return	fn_power_of_2(OSPF_tag_sourcebits - 1 + inst);
+}
+
+function fn_instancebit_is_set_in_ospf_tag (int inst)
+int instpathbits;
+{
+	instpathbits = fn_tag_to_path(ospf_tag) / fn_power_of_2(inst-1);
+	return	(instpathbits / 2) * 2 != instpathbits;
+}
+
+function fn_reentrybit_is_set_in_ospf_tag() {
+	return	fn_instancebit_is_set_in_ospf_tag(fn_tag_to_source(ospf_tag));
+}
+
+function fn_set_reentrybit_in_ospf_tag() {
+	ospf_tag = ospf_tag + fn_instance_to_tagbit(fn_tag_to_source(ospf_tag));
+}
+
+include "/usr/local/etc/bird.local.conf";
+
+/* Dort muss mindestens Folgendes definiert werden (Beispiel):
+
+router id 91.204.4.242;
+
+function fn_is_local_ospf_instance (int inst) {
+ 	case inst {
+		1: return true;
+		2: return true;
+		else: return false;
+	}
+}
+
+function fn_any_local_instancebit_is_set_in_ospf_tag () {
+	return	fn_instancebit_is_set_in_ospf_tag(1) ||
+		fn_instancebit_is_set_in_ospf_tag(2);
+}
+
+define Unrouted_local = [ 192.168.1.0/24+, 192.168.84.0/24+ ];
+*/
+
+define Babel_WLAN_metric_base = 1000;
+define Babel_WLAN_metric_inactive = 999;
+define OSPF_metric2_max = 16777215;
+define OSPF_preference_local	= 160;	/* > OSPF default = 150 */
+
+define HOT  = 0;
+define BEST = 1;
+define COLD = 2;
+
+##### Definitionen fuer alle bekannten IGP Instanzen:
+
+include "/usr/local/etc/bird.inst.conf";
+
+# Dort muss mindestens Folgendes definiert werden:
+#define potato_ospf1 = BEST; [... et al. ...]
+#function fn_instance_to_potato (int inst) -> int (HOT, ...)
+#function fn_proto_to_instance (string from_proto) -> int (1, 2, ...)
+#function fn_instance_to_bgpospf (int inst) -> string ("bgpXospfX")
+
+/* XXX zwecks Einrechnung der Babel Metrik, gehoert hier aber nicht hin: */
+function fn_a_Babel_WLAN_routes () {
+	return	ifname = "tap9";
+	};
+
+/* Bausteine fuer Filter. Namenskonventionen:
+   f_...	Filter (accept/reject)
+   fn_...	Funktion
+   ..._a_...	true => accept
+   ..._r_...	true => reject
+   ..._am_...	true => accept + modify
+*/
+
+function fn_a_Routed () {
+	return net ~ Routed;
+	};
+
+filter f_a_Routed {
+	if fn_a_Routed()
+	then accept;
+	else reject "Routed";
+	};
+
+function fn_r_Unrouted () {
+	return ! (net ~ Unrouted_global || net ~ Unrouted_local);
+	};
+
+filter f_r_Unrouted {
+	if fn_r_Unrouted()
+	then accept;
+	else reject "Unrouted";
+	};
+
+function fn_a_acceptable_routes () {
+	return fn_r_Unrouted() && fn_a_Routed();
+}
+ 
+/* Einrechnung der Babel Metrik: */
+function fn_include_Babel_WLAN_routes () {
+	case gw {
+		include "/var/run/bird.babeld.conf";
+		else: ospf_metric1 = ospf_metric1 + Babel_WLAN_metric_base + Babel_WLAN_metric_inactive;
+	}
+}
+
+function fn_debug_ospf_route (string str)
+{
+	print	str, " ", net, " ^", scope, " *", source,
+		" !", from, " :", gw, " (", preference, ") ",
+		igp_metric, "/", ospf_metric1, "/", ospf_metric2,
+ 		" [", ospf_tag, "]";
+		# Fuehrt zu:
+		# bird: filters, line 169: Can't operate with values of incompatible types
+		#" [", fn_tag_to_source(ospf_tag), "|", fn_tag_to_path(ospf_tag), "]";
+}
+
+function fn_debug_ospf_route_before (string str)
+{
+	printn str; fn_debug_ospf_route("?");
+}
+
+function fn_debug_ospf_route_after (string str)
+{
+	printn str; fn_debug_ospf_route("!");
+}
+
+function fn_am_local_to_ospf_table () {
+	if ! (proto ~ "ospf*") &&
+	   fn_a_acceptable_routes()
+	then if ifname ~ "lo0"
+	     then return false;	
+	     else { if preference < OSPF_preference_local
+		    then preference = OSPF_preference_local;
+		    return true; }
+	else return false;
+}
+
+function fn_am_local_to_ospf_export () {
+	if ! (proto ~ "*ospf*") &&
+	   fn_a_acceptable_routes()
+	then {	if ifname ~ "lo0"
+	      	then return false;
+	      	else # geroutete loopback Adressen auch per OSPF stubnet!
+		     if ifname ~ "lo*"
+		     then ospf_metric1 = 1;
+		     else ospf_metric1 = 10;
+		ospf_metric2 = 0;
+	       return true; }
+	else return false;
+}
+
+function fn_import_ospf_master (int from_instance) {
+	if ! fn_a_acceptable_routes()
+	then return false;
+	# Schleifenvermeidung: routes mit tags von OSPF-Instanzen,
+	# an denen dieser Router teilnimmt, sind schonmal hier
+	# durchgelaufen, und zwar mit tag = 0, d.h. ohne Uebergang
+	# zwischen OSPF-Instanzen. (Evtl. Ausnahme: Partitionierung
+	# der source Instanz, sodass die urspruengliche route nicht
+	# mit source = 0 hier ankam, sondern nur per Transit.)
+	else if ospf_tag != 0
+	then {
+		if fn_instance_to_potato(from_instance) = HOT
+		   # TBD || fn_instance_to_transit(from_instance) = false
+		then	# kein Transit durch hot potato Instanzen
+			return false;
+		else if	fn_is_local_ospf_instance(fn_tag_to_source(ospf_tag)) ||
+			fn_any_local_instancebit_is_set_in_ospf_tag()
+		then	# re-entry
+			if ! fn_reentrybit_is_set_in_ospf_tag()
+			then	# wg. counting-to-infinity
+				fn_set_reentrybit_in_ospf_tag();
+	     }
+	case from_instance {
+		/* XXX zwecks Einrechnung der Babel Metrik, gehoert hier aber nicht hin: */
+		# metric mittels /var/run/bird.babeld.conf (hoch)setzen:
+		2: fn_include_Babel_WLAN_routes();
+	     	}
+	return true;
+}
+
+
+function fn_import_master_ospf (string from_proto) {
+	return proto = from_proto;
+}
+
+/* Funktioniert nicht als Funktion, aber als Filter,
+   s. protocol pipe master2ospfX in bird.instX.conf.
+   Grumpf:-(bird 1.5.0)
+function fn_export_master_ospf () {
+	if proto ~ "ospf*"
+	then return false;
+	else return fn_am_local_to_ospf_table();
+}
+*/
+
+function fn_am_master_to_bgpospf (int dest_instance)
+int from_instance;
+{
+	if fn_a_acceptable_routes()
+	then {	from_instance = fn_proto_to_instance(proto);
+		if ospf_tag = 0		# (lokale Route, keine Transitroute)
+		then {	# route entstammt einer IGP Instanz, an der dieser
+			# router teilnimmt. Beim Uebergang in eine andere
+			# IGP Instanz muss diese route, die gerade ein
+			# lokales IGP verlaesst, mit dem tag dieser Instanz
+			# versehen werden. Kommt die route dann spaeter
+			# per transit wieder zur Urprungs-Instanz zurueck,
+			# kann sie dank des tags als Rundlauefer erkannt
+			# und entsprechend schleifenbehandelt werden.
+			ospf_tag = from_instance;
+			return true;
+		     }
+		else	if fn_instance_to_potato(from_instance) = HOT
+			   # TBD || fn_instance_to_transit(from_instance) = false
+			then	# kein Transit durch HOT Instanzen wg. Verlust der ursprünglichen Metrik
+				return false;
+			else {	if fn_reentrybit_is_set_in_ospf_tag() &&
+				   fn_instancebit_is_set_in_ospf_tag(dest_instance)
+				then	# kein counting-to-infinity
+					return false;
+				# Transit-IGP, aus dem die Route gerade kommt, in die Route "einkerben"
+				if ! fn_instancebit_is_set_in_ospf_tag(from_instance)
+				then	ospf_tag = ospf_tag + fn_instance_to_tagbit(from_instance);
+				return true;
+			     }
+	     }
+	else return false;
+}
+
+function fn_export_master_bgpospf (string dest_proto)
+int dest_instance;
+{
+	dest_instance = fn_proto_to_instance(dest_proto);
+	printn "master2bgp"; fn_debug_ospf_route_before(dest_proto);
+	if proto ~ "ospf*" &&
+	   proto != dest_proto &&
+	   fn_am_master_to_bgpospf(dest_instance)
+	then {	printn "master2bgp"; fn_debug_ospf_route_after(dest_proto);
+		bgp_local_pref = preference;
+		bgp_path.prepend(ospf_tag);
+		# optimal:
+		# -> E1 mit metric1 = Summe
+		# hot potato ("closest exit"):
+		# -> E1 mit metric1 = 0, # geht nicht: metric2 = Summe
+		# retour: automatisch mit mit metric1 = Summe, metric2 = 0
+		# cold potato ("best exit", RFC4451):
+		# -> E2 mit metric2 = Summe
+		# ?: wie geht retour E2 -> E1, d.h. wie funktioniert
+		# eine Unterscheidung von ursprünglichen E2 routes?
+		# flag im ospf_tag?
+		if # XXX geht nicht: ospf_metric2 = 16777235
+		     ospf_metric2 = OSPF_metric2_max
+		then
+			bgp_med = ospf_metric1;
+		else
+			bgp_med = ospf_metric2 + ospf_metric1;
+		# zZ unbenutzt, erscheint im show all als [ASXi]/[ASXe]
+		if ospf_tag != 0
+		then
+			if fn_reentrybit_is_set_in_ospf_tag()
+			then
+				bgp_origin = 2;
+			else
+				bgp_origin = 1;
+		else
+			bgp_origin = 0;
+		accept;
+	     }
+	else reject;
+}
+
+function fn_import_bgpospf ()
+{
+	preference = bgp_local_pref;
+	return true;
+}
+
+function fn_export_ospf (int dest_instance)
+string proto_bgpospf;
+int potato_ospf;
+{
+	proto_bgpospf = fn_instance_to_bgpospf(dest_instance);
+	potato_ospf = fn_instance_to_potato(dest_instance);
+	printn "export-", dest_instance; fn_debug_ospf_route_before("");
+	if fn_am_local_to_ospf_export()
+	then return true;
+	else if proto = proto_bgpospf
+	then {	ospf_tag = bgp_path.first;
+		# optimal:
+		# -> E1 mit metric1 = Summe
+		# hot potato ("closest exit"):
+		# -> E1 mit metric1 = 0, metric2 = Summe
+		# retour: automatisch mit mit metric1 = Summe, metric2 = 0
+		# cold potato ("best exit", RFC4451):
+		# -> E2 mit metric2 = Summe
+		# ?: wie geht retour E2 -> E1, d.h. wie funktioniert
+		#    eine Unterscheidung von ursprünglichen E2 routes?
+		#    also flag im ospf_tag kodieren?
+		# !: nein, keine E2 routen als E2 durchlassen,
+		#    weil das jede Instanz selbst entscheiden soll,
+		#    also nur bei cold potato auf E2 setzen (lassen)
+		#
+		if potato_ospf = BEST
+			then {
+				# igp_metric = bgp_med;
+				# bgp_med = 0;
+				# scope = SCOPE_ORGANIZATION;
+				ospf_metric1 = bgp_med;
+			     }
+			else if potato_ospf = HOT
+			then {
+				# geht nicht, wird beim Setzen von
+				# von ospf_metric1 genichtet:
+				# ospf_metric2 = bgp_med;
+				ospf_metric1 = 0;
+				# XXX instance mit hot potato
+				# XXX darf kein Transit sein!
+				# XXX => keine tag routes exportieren
+			     }
+			else if potato_ospf = COLD
+			     then ospf_metric2 = bgp_med;
+			printn "export-", dest_instance; fn_debug_ospf_route_after("");
+			return true;
+	     }
+	else return false;
+}
+
+protocol device {
+	scan time 10;
+}
+
+/* wg. BSD: */
+protocol direct {
+}
+
+protocol kernel kernel0 {
+	learn on;
+	scan time 5;
+	import filter f_r_Unrouted;
+	export filter f_r_Unrouted;
+}
+
+/* XXX zwecks Einrechnung der Babel Metrik, gehoert hier aber nicht hin: */
+table fib4table;
+protocol kernel kernel4 {
+	description "babel FIB 4";
+	kernel table 4;
+	table fib4table;
+	learn on;
+	scan time 10;	
+}
+
+##### Definition der IGP Instanzen, an denen dieser Router teilnimmt:
+
+include "/usr/local/etc/bird.inst.local.conf";