[pim] Initial pim 0.155
diff --git a/pimd/TODO b/pimd/TODO
new file mode 100644
index 0000000..7a2ca0b
--- /dev/null
+++ b/pimd/TODO
@@ -0,0 +1,356 @@
+# $QuaggaId: $Format:%an, %ai, %h$ $
+
+T1 DONE Implement debug command
+ test pim receive join
+
+T2 DONE Implement debug command
+ test pim receive prune
+
+T3 DONE Per-interface Downstream (S,G) state machine
+ (RFC 4601 4.5.3. Receiving (S,G) Join/Prune Messages)
+
+T4 DONE Upstream (S,G) state machine
+ (RFC 4601 4.5.7. Sending (S,G) Join/Prune Messages)
+
+T5 DONE Verify Data Packet Forwarding Rules
+ RFC 4601 4.2. Data Packet Forwarding Rules
+ RFC 4601 4.8.2. PIM-SSM-Only Routers
+
+ Additionally, the Packet forwarding rules of Section 4.2 can be
+ simplified in a PIM-SSM-only router:
+
+ iif is the incoming interface of the packet.
+ oiflist = NULL
+ if (iif == RPF_interface(S) AND UpstreamJPState(S,G) == Joined) {
+ oiflist = inherited_olist(S,G)
+ } else if (iif is in inherited_olist(S,G)) {
+ send Assert(S,G) on iif
+ }
+ oiflist = oiflist (-) iif
+ forward packet on all interfaces in oiflist
+
+ Macro:
+ inherited_olist(S,G) =
+ joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G)
+
+T6 DONE Implement (S,G) Assert state machine (RFC 4601, section 4.6.1).
+ Changes in pim_ifchannel.ifassert_winner should trigger
+ pim_upstream_update_join_desired().
+ Depends on TODO T27.
+ Depends on TODO T33.
+ See also CAVEAT C7.
+ See also: RFC 4601 4.5.7. Sending (S,G) Join/Prune Messages
+ Transitions from Joined State
+ RPF'(S,G) changes due to an Assert
+
+ http://www.hep.ucl.ac.uk/~ytl/multi-cast/pim-dm_01.html:
+
+ The PIM Assert mechanism is used to shutoff duplicate flows onto
+ the same multiaccess network. Routers detect this condiction when
+ they receive an (S,G) packet via a multi-access interface that is
+ in the (S,G) OIL. This causes the routers to send Assert
+ Messages.
+
+ Note that neighbors will not accept Join/Prune or Assert messages
+ from a router unless they have first heard a Hello message from that
+ router. Thus, if a router needs to send a Join/Prune or Assert
+ message on an interface on which it has not yet sent a Hello message
+ with the currently configured IP address, then it MUST immediately
+ send the relevant Hello message without waiting for the Hello Timer
+ to expire, followed by the Join/Prune or Assert message.
+
+T7 DONE Implement hello option: LAN Prune Delay
+
+T8 DONE Implement J/P_Override_Interval(I)
+ Depends on TODO T7.
+ See pim_ifchannel.c, pim_ifchannel_prune(), jp_override_interval.
+
+T9 DONE Detect change in IGMPv3 RPF interface/next-hop for S and update.
+ channel_oil vif index accordingly ?
+ Beware accidentaly adding looped MFC entries (IIF=OIF).
+
+T10 DONE React to (S,G) join directed to another upstream address. See
+ also:
+
+ RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages
+
+ If a router wishes to propagate a Join(S,G) upstream, it must also
+ watch for messages on its upstream interface from other routers on
+ that subnet, and these may modify its behavior. If it sees a
+ Join(S,G) to the correct upstream neighbor, it should suppress its
+ own Join(S,G). If it sees a Prune(S,G), Prune(S,G,rpt), or
+ Prune(*,G) to the correct upstream neighbor towards S, it should
+ be prepared to override that prune by scheduling a Join(S,G) to be
+ sent almost immediately.
+
+T11 DONE Review protocol modifications for SSM
+ (RFC 4601 4.8.1. Protocol Modifications for SSM Destination
+ Addresses)
+
+T12 DONE Review updates of RPF entries.
+ FIXME pim_upstream.c send_join():
+ Currently only one upstream state is affected by detection of RPF change.
+ RPF change should affect all upstream states sharing the RPF cache.
+
+T13 DONE Check that RFC macros using S,G,RPF_interface(S) are actually
+ implemented with this strategy:
+ rpf_ifch=find_ifch(up->rpf->interface).
+ See pim_rpf.c pim_rpf_find_rpf_addr() for a correct example.
+
+ $ grep -i macro pimd/*.c
+ pimd/pim_iface.c: RFC 4601: 4.1.6. State Summarization Macros
+ pimd/pim_ifchannel.c: RFC 4601: 4.6.5. Assert State Macros
+ pimd/pim_ifchannel.c: RFC 4601: 4.1.6. State Summarization Macros
+ pimd/pim_ifchannel.c: RFC 4601: 4.1.6. State Summarization Macros
+ pimd/pim_ifchannel.c: RFC 4601: 4.6.5. Assert State Macros
+ pimd/pim_ifchannel.c: Macro:
+ pimd/pim_rpf.c: RFC 4601: 4.1.6. State Summarization Macros
+
+T14 DONE Send Assert(S,G) on iif as response to WRONGVIF kernel upcall.
+ See pim_mroute.c mroute_msg().
+
+T15 DONE Interface command to statically join (S,G).
+ interface eth0
+ ip igmp join-group 239.1.1.1 source 1.1.1.1
+
+T16 DONE RPF'(S,G) lookup is not working for S reachable with default route.
+ See "RPF'(S,G) not found" in pim_rpf_update() from pim_rpf.c.
+ Zebra daemon RIB is not reflecting changes in kernel routes
+ accurately?
+
+T17 DONE Prevent CLI from creating bogus interfaces.
+ Example:
+ conf t
+ interface xxx
+
+T18 Consider reliable pim solution (refresh reduction)
+ A Reliable Transport Mechanism for PIM
+ http://tools.ietf.org/wg/pim/draft-ietf-pim-port/
+ PORT=PIM-Over-Reliable-Transport
+
+T19 DONE Fix self as neighbor
+ See mailing list post:
+ http://lists.gnu.org/archive/html/qpimd-users/2009-04/msg00000.html
+
+T20 DONE Fix debug message: "pim_neighbor_update: internal error:
+ trying to replace same prefix list"
+ See mailing list post:
+ http://lists.gnu.org/archive/html/qpimd-users/2009-04/msg00000.html
+
+T21 DONE Clean-up PIM/IGMP interface mismatch debugging
+ See option PIM_CHECK_RECV_IFINDEX_SANITY in pimd/Makefile.am
+ See mailing list post:
+ http://lists.nongnu.org/archive/html/qpimd-users/2009-04/msg00003.html
+
+T22 DONE IGMP must be protected against adding looped MFC entries
+ created by both source and receiver attached to the same
+ interface.
+
+T23 DONE libzebra crash after zclient_lookup_nexthop.
+ See mailing list post:
+ http://lists.nongnu.org/archive/html/qpimd-users/2009-04/msg00008.html
+
+T24 DONE zserv may return recursive routes:
+ - nexthop type is set to ZEBRA_NEXTHOP_IPV4
+ - ifindex is not reported
+ - calls expecting ifindex (fib_lookup_if_vif_index) are disrupted
+ See also this mailing list post:
+ [PATCH 21/21] Link detect and recursive routes
+ http://www.gossamer-threads.com/lists/quagga/dev/17564
+
+T25 DONE Zclient nexthop lookup missing OSPF route to 1.1.1.1/32
+ See also:
+ pim_zlookup.c zclient_lookup_nexthop misses OSPF 1.1.1.1/32
+ zebra/zebra_vty.c show_ip_route_addr_cmd hits OSPF 1.1.1.1/32
+
+T26 DONE Zebra daemon is marking recursive static route as inactive.
+
+ FIXED: zebra daemon was incorrectly marking recursive routes
+ pointing to kernel routes as inactive:
+ zebra/zebra_rib.c nexthop_active_ipv4:
+ -- Original:
+ else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL))
+ -- Fixed:
+ else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) ||
+ match->type == ZEBRA_ROUTE_KERNEL)
+
+ Old problem description:
+
+ This prevents rib_match_ipv4 from returning its nexthop:
+ client: pim_zlookup.c zclient_read_nexthop
+ server: zebra/zserv.c zsend_ipv4_nexthop_lookup_v2 -> rib_match_ipv4
+
+ Kernel route is injected into zebra in zebra_rib.c rib_add_ipv4
+ Examples:
+ rt_netlink.c:726: rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0);
+ rt_netlink.c:864: rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0);
+
+ This patch didn't fix the issue:
+ [PATCH 21/21] Link detect and recursive routes
+ http://www.gossamer-threads.com/lists/quagga/dev/17564
+
+ See the example below for the route 2.2.2.2.
+
+bash# route add -host 1.1.1.1 gw 127.0.0.1
+bash# route add -host 2.2.2.2 gw 1.1.1.1
+bash# netstat -nvr
+Kernel IP routing table
+Destination Gateway Genmask Flags MSS Window irtt Iface
+2.2.2.2 1.1.1.1 255.255.255.255 UGH 0 0 0 lo
+1.1.1.1 127.0.0.1 255.255.255.255 UGH 0 0 0 lo
+192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
+0.0.0.0 192.168.0.2 0.0.0.0 UG 0 0 0 eth0
+bash#
+
+zebra# sh ip route
+Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,
+ I - ISIS, B - BGP, > - selected route, * - FIB route
+
+K>* 0.0.0.0/0 via 192.168.0.2, eth0
+K>* 1.1.1.1/32 via 127.0.0.1, lo
+K * 2.2.2.2/32 via 1.1.1.1, lo inactive
+C>* 127.0.0.0/8 is directly connected, lo
+C>* 192.168.0.0/24 is directly connected, eth0
+
+quagga-pimd-router# sh ip route 1.1.1.1
+Address NextHop Interface Metric Preference
+1.1.1.1 127.0.0.1 lo 0 0
+quagga-pimd-router#
+quagga-pimd-router# sh ip route 2.2.2.2
+Address NextHop Interface Metric Preference
+2.2.2.2 192.168.0.2 eth0 0 0
+quagga-pimd-router#
+
+T27 DONE Implement debug command
+ test pim receive assert
+ See also TODO T6: (S,G) Assert state machine.
+
+T28 DONE Bad IPv4 address family=02 in Join/Prune dump
+ Reported by Andrew Lunn <andrew.lunn@ascom.ch>
+
+ # 58-byte pim v2 Join/Prune dump
+ # ------------------------------
+ # IPv4 address family=02 is wrong, correct IPv4 address family is 01
+ # See http://www.iana.org/assignments/address-family-numbers
+ #
+ c8XX YY03 : ip src 200.xx.yy.3
+ e000 000d : ip dst 224.0.0.13
+ 9404 0000 : ip router alert option 148.4.0.0
+ 2300 ab13 : pimv2,type=3 res=00 checksum=ab13
+ 0200 : upstream family=02, encoding=00
+ c8XX YY08 : upstream 200.xx.yy.8
+ 0001 00d2 : res=00 groups=01 holdtime=00d2
+ 0200 0020 : group family=02, encoding=00, res=00, mask_len=20
+ ef01 0101 : group address 239.1.1.1
+ 0001 0000 : joined=0001 pruned=0000
+ 0200 0020 : source family=02, encoding=00, res=00, mask_len=20
+ 0101 0101 : source address 1.1.1.1
+
+T29 DONE Reset interface PIM-hello-sent counter when primary address changes
+ See pim_ifp->pim_ifstat_hello_sent
+
+ RFC 4601: 4.3.1. Sending Hello Messages
+
+ Thus, if a router needs to send a Join/Prune or Assert message on
+ an interface on which it has not yet sent a Hello message with the
+ currently configured IP address, then it MUST immediately send the
+ relevant Hello message without waiting for the Hello Timer to
+ expire, followed by the Join/Prune or Assert message.
+
+T30 DONE Run interface DR election when primary address changes
+ Reported by Andrew Lunn <andrew.lunn@ascom.ch>
+ See pim_if_dr_election().
+
+T31 If an interface changes one of its secondary IP addresses, a Hello
+ message with an updated Address_List option and a non-zero
+ HoldTime should be sent immediately.
+ See also CAVEAT C15.
+ See also RFC 4601: 4.3.1. Sending Hello Messages
+
+T32 Detection of interface primary address changes may fail when there
+ are multiple addresses.
+ See also CAVEAT C14.
+
+ pim_find_primary_addr() should return interface primary address
+ from connected list. Currently it returns the first address.
+
+ Zebra daemon "show int" is able to keep the primary address as
+ first address.
+
+T33 DONE Implement debug command: test pim receive upcall
+ See also TODO T6: (S,G) Assert state machine.
+
+T34 DONE assert_action_a1
+
+T35 DONE Review macros depending on interface I.
+
+ See also: grep ,I\) pimd/*.c
+
+ For the case (S,G,I) check if I is either
+ 1) interface attached to this per-interface S,G state (don't think so)
+ or
+ 2) an arbitrary interface (most probably)
+
+ For the arbitrary interface case (2), consider representing
+ interface ifp as its primary address (struct in_addr ifaddr). The
+ benefit is in_addr does not need to be dereferenced, so it does
+ not demand protection against crashes.
+
+T36 DONE React to zebra daemon link-detect up/down notification.
+ pim_ifp->primary_address is managed by detect_primary_address_change()
+ depending on to ifp->connected (managed by zebra_interface_address_read()).
+
+T37 DONE Review list of variables which may affect pim_upstream.c
+ pim_upstream_evaluate_join_desired().
+ Call pim_upstream_update_join_desired() accordingly.
+
+ See the order of invokation:
+ pim_if_dr_election(ifp);
+ pim_if_update_join_desired(pim_ifp); /* depends on DR */
+ pim_if_update_could_assert(ifp); /* depends on DR */
+ pim_if_update_my_assert_metric(ifp); /* depends on could_assert */
+
+ join_desired depends on:
+ pim_ifp->primary_address
+ pim_ifp->pim_dr_addr
+ ch->ifassert_winner_metric
+ ch->ifassert_winner
+ ch->local_ifmembership
+ ch->ifjoin_state
+ ch->upstream->rpf.source_nexthop.mrib_metric_preference
+ ch->upstream->rpf.source_nexthop.mrib_route_metric
+ ch->upstream->rpf.source_nexthop.interface
+
+T38 DONE Detect change in AssertTrackingDesired(S,G,I)
+
+ See the order of invokation:
+ dr_election: none
+ update_join_desired: depends on DR
+ update_tracking_desired: depends on DR, join_desired
+
+ AssertTrackingDesired(S,G,I) depends on:
+ pim_ifp->primary_address
+ pim_ifp->pim_dr_addr
+ ch->local_ifmembership
+ ch->ifassert_winner
+ ch->ifjoin_state
+ ch->upstream->rpf.source_nexthop.interface
+ PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(ch->upstream->flags)
+
+T39 DONE AssertTrackingDesired: flags is not matching evaluation
+
+ # show ip pim assert-internal
+ CA: CouldAssert
+ ECA: Evaluate CouldAssert
+ ATD: AssertTrackingDesired
+ eATD: Evaluate AssertTrackingDesired
+
+ Interface Address Source Group CA eCA ATD eATD
+ eth0 192.168.1.100 1.1.1.1 239.1.1.1 no no no yes
+ #
+
+T40 Lightweight MLDv2
+ http://www.ietf.org/internet-drafts/draft-ietf-mboned-lightweight-igmpv3-mldv2-05.txt
+ http://www.ietf.org/html.charters/mboned-charter.html
+
+-x-