Everton Marques | 871dbcf | 2009-08-11 15:43:05 -0300 | [diff] [blame] | 1 | # $QuaggaId: $Format:%an, %ai, %h$ $ |
| 2 | |
| 3 | T1 DONE Implement debug command |
| 4 | test pim receive join |
| 5 | |
| 6 | T2 DONE Implement debug command |
| 7 | test pim receive prune |
| 8 | |
| 9 | T3 DONE Per-interface Downstream (S,G) state machine |
| 10 | (RFC 4601 4.5.3. Receiving (S,G) Join/Prune Messages) |
| 11 | |
| 12 | T4 DONE Upstream (S,G) state machine |
| 13 | (RFC 4601 4.5.7. Sending (S,G) Join/Prune Messages) |
| 14 | |
| 15 | T5 DONE Verify Data Packet Forwarding Rules |
| 16 | RFC 4601 4.2. Data Packet Forwarding Rules |
| 17 | RFC 4601 4.8.2. PIM-SSM-Only Routers |
| 18 | |
| 19 | Additionally, the Packet forwarding rules of Section 4.2 can be |
| 20 | simplified in a PIM-SSM-only router: |
| 21 | |
| 22 | iif is the incoming interface of the packet. |
| 23 | oiflist = NULL |
| 24 | if (iif == RPF_interface(S) AND UpstreamJPState(S,G) == Joined) { |
| 25 | oiflist = inherited_olist(S,G) |
| 26 | } else if (iif is in inherited_olist(S,G)) { |
| 27 | send Assert(S,G) on iif |
| 28 | } |
| 29 | oiflist = oiflist (-) iif |
| 30 | forward packet on all interfaces in oiflist |
| 31 | |
| 32 | Macro: |
| 33 | inherited_olist(S,G) = |
| 34 | joins(S,G) (+) pim_include(S,G) (-) lost_assert(S,G) |
| 35 | |
| 36 | T6 DONE Implement (S,G) Assert state machine (RFC 4601, section 4.6.1). |
| 37 | Changes in pim_ifchannel.ifassert_winner should trigger |
| 38 | pim_upstream_update_join_desired(). |
| 39 | Depends on TODO T27. |
| 40 | Depends on TODO T33. |
| 41 | See also CAVEAT C7. |
| 42 | See also: RFC 4601 4.5.7. Sending (S,G) Join/Prune Messages |
| 43 | Transitions from Joined State |
| 44 | RPF'(S,G) changes due to an Assert |
| 45 | |
| 46 | http://www.hep.ucl.ac.uk/~ytl/multi-cast/pim-dm_01.html: |
| 47 | |
| 48 | The PIM Assert mechanism is used to shutoff duplicate flows onto |
| 49 | the same multiaccess network. Routers detect this condiction when |
| 50 | they receive an (S,G) packet via a multi-access interface that is |
| 51 | in the (S,G) OIL. This causes the routers to send Assert |
| 52 | Messages. |
| 53 | |
| 54 | Note that neighbors will not accept Join/Prune or Assert messages |
| 55 | from a router unless they have first heard a Hello message from that |
| 56 | router. Thus, if a router needs to send a Join/Prune or Assert |
| 57 | message on an interface on which it has not yet sent a Hello message |
| 58 | with the currently configured IP address, then it MUST immediately |
| 59 | send the relevant Hello message without waiting for the Hello Timer |
| 60 | to expire, followed by the Join/Prune or Assert message. |
| 61 | |
| 62 | T7 DONE Implement hello option: LAN Prune Delay |
| 63 | |
| 64 | T8 DONE Implement J/P_Override_Interval(I) |
| 65 | Depends on TODO T7. |
| 66 | See pim_ifchannel.c, pim_ifchannel_prune(), jp_override_interval. |
| 67 | |
| 68 | T9 DONE Detect change in IGMPv3 RPF interface/next-hop for S and update. |
| 69 | channel_oil vif index accordingly ? |
| 70 | Beware accidentaly adding looped MFC entries (IIF=OIF). |
| 71 | |
| 72 | T10 DONE React to (S,G) join directed to another upstream address. See |
| 73 | also: |
| 74 | |
| 75 | RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages |
| 76 | |
| 77 | If a router wishes to propagate a Join(S,G) upstream, it must also |
| 78 | watch for messages on its upstream interface from other routers on |
| 79 | that subnet, and these may modify its behavior. If it sees a |
| 80 | Join(S,G) to the correct upstream neighbor, it should suppress its |
| 81 | own Join(S,G). If it sees a Prune(S,G), Prune(S,G,rpt), or |
| 82 | Prune(*,G) to the correct upstream neighbor towards S, it should |
| 83 | be prepared to override that prune by scheduling a Join(S,G) to be |
| 84 | sent almost immediately. |
| 85 | |
| 86 | T11 DONE Review protocol modifications for SSM |
| 87 | (RFC 4601 4.8.1. Protocol Modifications for SSM Destination |
| 88 | Addresses) |
| 89 | |
| 90 | T12 DONE Review updates of RPF entries. |
| 91 | FIXME pim_upstream.c send_join(): |
| 92 | Currently only one upstream state is affected by detection of RPF change. |
| 93 | RPF change should affect all upstream states sharing the RPF cache. |
| 94 | |
| 95 | T13 DONE Check that RFC macros using S,G,RPF_interface(S) are actually |
| 96 | implemented with this strategy: |
| 97 | rpf_ifch=find_ifch(up->rpf->interface). |
| 98 | See pim_rpf.c pim_rpf_find_rpf_addr() for a correct example. |
| 99 | |
| 100 | $ grep -i macro pimd/*.c |
| 101 | pimd/pim_iface.c: RFC 4601: 4.1.6. State Summarization Macros |
| 102 | pimd/pim_ifchannel.c: RFC 4601: 4.6.5. Assert State Macros |
| 103 | pimd/pim_ifchannel.c: RFC 4601: 4.1.6. State Summarization Macros |
| 104 | pimd/pim_ifchannel.c: RFC 4601: 4.1.6. State Summarization Macros |
| 105 | pimd/pim_ifchannel.c: RFC 4601: 4.6.5. Assert State Macros |
| 106 | pimd/pim_ifchannel.c: Macro: |
| 107 | pimd/pim_rpf.c: RFC 4601: 4.1.6. State Summarization Macros |
| 108 | |
| 109 | T14 DONE Send Assert(S,G) on iif as response to WRONGVIF kernel upcall. |
| 110 | See pim_mroute.c mroute_msg(). |
| 111 | |
| 112 | T15 DONE Interface command to statically join (S,G). |
| 113 | interface eth0 |
| 114 | ip igmp join-group 239.1.1.1 source 1.1.1.1 |
| 115 | |
| 116 | T16 DONE RPF'(S,G) lookup is not working for S reachable with default route. |
| 117 | See "RPF'(S,G) not found" in pim_rpf_update() from pim_rpf.c. |
| 118 | Zebra daemon RIB is not reflecting changes in kernel routes |
| 119 | accurately? |
| 120 | |
| 121 | T17 DONE Prevent CLI from creating bogus interfaces. |
| 122 | Example: |
| 123 | conf t |
| 124 | interface xxx |
| 125 | |
| 126 | T18 Consider reliable pim solution (refresh reduction) |
| 127 | A Reliable Transport Mechanism for PIM |
| 128 | http://tools.ietf.org/wg/pim/draft-ietf-pim-port/ |
| 129 | PORT=PIM-Over-Reliable-Transport |
| 130 | |
| 131 | T19 DONE Fix self as neighbor |
| 132 | See mailing list post: |
| 133 | http://lists.gnu.org/archive/html/qpimd-users/2009-04/msg00000.html |
| 134 | |
| 135 | T20 DONE Fix debug message: "pim_neighbor_update: internal error: |
| 136 | trying to replace same prefix list" |
| 137 | See mailing list post: |
| 138 | http://lists.gnu.org/archive/html/qpimd-users/2009-04/msg00000.html |
| 139 | |
| 140 | T21 DONE Clean-up PIM/IGMP interface mismatch debugging |
| 141 | See option PIM_CHECK_RECV_IFINDEX_SANITY in pimd/Makefile.am |
| 142 | See mailing list post: |
| 143 | http://lists.nongnu.org/archive/html/qpimd-users/2009-04/msg00003.html |
| 144 | |
| 145 | T22 DONE IGMP must be protected against adding looped MFC entries |
| 146 | created by both source and receiver attached to the same |
| 147 | interface. |
| 148 | |
| 149 | T23 DONE libzebra crash after zclient_lookup_nexthop. |
| 150 | See mailing list post: |
| 151 | http://lists.nongnu.org/archive/html/qpimd-users/2009-04/msg00008.html |
| 152 | |
| 153 | T24 DONE zserv may return recursive routes: |
| 154 | - nexthop type is set to ZEBRA_NEXTHOP_IPV4 |
| 155 | - ifindex is not reported |
| 156 | - calls expecting ifindex (fib_lookup_if_vif_index) are disrupted |
| 157 | See also this mailing list post: |
| 158 | [PATCH 21/21] Link detect and recursive routes |
| 159 | http://www.gossamer-threads.com/lists/quagga/dev/17564 |
| 160 | |
| 161 | T25 DONE Zclient nexthop lookup missing OSPF route to 1.1.1.1/32 |
| 162 | See also: |
| 163 | pim_zlookup.c zclient_lookup_nexthop misses OSPF 1.1.1.1/32 |
| 164 | zebra/zebra_vty.c show_ip_route_addr_cmd hits OSPF 1.1.1.1/32 |
| 165 | |
| 166 | T26 DONE Zebra daemon is marking recursive static route as inactive. |
| 167 | |
| 168 | FIXED: zebra daemon was incorrectly marking recursive routes |
| 169 | pointing to kernel routes as inactive: |
| 170 | zebra/zebra_rib.c nexthop_active_ipv4: |
| 171 | -- Original: |
| 172 | else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) |
| 173 | -- Fixed: |
| 174 | else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) || |
| 175 | match->type == ZEBRA_ROUTE_KERNEL) |
| 176 | |
| 177 | Old problem description: |
| 178 | |
| 179 | This prevents rib_match_ipv4 from returning its nexthop: |
| 180 | client: pim_zlookup.c zclient_read_nexthop |
| 181 | server: zebra/zserv.c zsend_ipv4_nexthop_lookup_v2 -> rib_match_ipv4 |
| 182 | |
| 183 | Kernel route is injected into zebra in zebra_rib.c rib_add_ipv4 |
| 184 | Examples: |
| 185 | rt_netlink.c:726: rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0); |
| 186 | rt_netlink.c:864: rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0); |
| 187 | |
| 188 | This patch didn't fix the issue: |
| 189 | [PATCH 21/21] Link detect and recursive routes |
| 190 | http://www.gossamer-threads.com/lists/quagga/dev/17564 |
| 191 | |
| 192 | See the example below for the route 2.2.2.2. |
| 193 | |
| 194 | bash# route add -host 1.1.1.1 gw 127.0.0.1 |
| 195 | bash# route add -host 2.2.2.2 gw 1.1.1.1 |
| 196 | bash# netstat -nvr |
| 197 | Kernel IP routing table |
| 198 | Destination Gateway Genmask Flags MSS Window irtt Iface |
| 199 | 2.2.2.2 1.1.1.1 255.255.255.255 UGH 0 0 0 lo |
| 200 | 1.1.1.1 127.0.0.1 255.255.255.255 UGH 0 0 0 lo |
| 201 | 192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0 |
| 202 | 0.0.0.0 192.168.0.2 0.0.0.0 UG 0 0 0 eth0 |
| 203 | bash# |
| 204 | |
| 205 | zebra# sh ip route |
| 206 | Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF, |
| 207 | I - ISIS, B - BGP, > - selected route, * - FIB route |
| 208 | |
| 209 | K>* 0.0.0.0/0 via 192.168.0.2, eth0 |
| 210 | K>* 1.1.1.1/32 via 127.0.0.1, lo |
| 211 | K * 2.2.2.2/32 via 1.1.1.1, lo inactive |
| 212 | C>* 127.0.0.0/8 is directly connected, lo |
| 213 | C>* 192.168.0.0/24 is directly connected, eth0 |
| 214 | |
| 215 | quagga-pimd-router# sh ip route 1.1.1.1 |
| 216 | Address NextHop Interface Metric Preference |
| 217 | 1.1.1.1 127.0.0.1 lo 0 0 |
| 218 | quagga-pimd-router# |
| 219 | quagga-pimd-router# sh ip route 2.2.2.2 |
| 220 | Address NextHop Interface Metric Preference |
| 221 | 2.2.2.2 192.168.0.2 eth0 0 0 |
| 222 | quagga-pimd-router# |
| 223 | |
| 224 | T27 DONE Implement debug command |
| 225 | test pim receive assert |
| 226 | See also TODO T6: (S,G) Assert state machine. |
| 227 | |
| 228 | T28 DONE Bad IPv4 address family=02 in Join/Prune dump |
| 229 | Reported by Andrew Lunn <andrew.lunn@ascom.ch> |
| 230 | |
| 231 | # 58-byte pim v2 Join/Prune dump |
| 232 | # ------------------------------ |
| 233 | # IPv4 address family=02 is wrong, correct IPv4 address family is 01 |
| 234 | # See http://www.iana.org/assignments/address-family-numbers |
| 235 | # |
| 236 | c8XX YY03 : ip src 200.xx.yy.3 |
| 237 | e000 000d : ip dst 224.0.0.13 |
| 238 | 9404 0000 : ip router alert option 148.4.0.0 |
| 239 | 2300 ab13 : pimv2,type=3 res=00 checksum=ab13 |
| 240 | 0200 : upstream family=02, encoding=00 |
| 241 | c8XX YY08 : upstream 200.xx.yy.8 |
| 242 | 0001 00d2 : res=00 groups=01 holdtime=00d2 |
| 243 | 0200 0020 : group family=02, encoding=00, res=00, mask_len=20 |
| 244 | ef01 0101 : group address 239.1.1.1 |
| 245 | 0001 0000 : joined=0001 pruned=0000 |
| 246 | 0200 0020 : source family=02, encoding=00, res=00, mask_len=20 |
| 247 | 0101 0101 : source address 1.1.1.1 |
| 248 | |
| 249 | T29 DONE Reset interface PIM-hello-sent counter when primary address changes |
| 250 | See pim_ifp->pim_ifstat_hello_sent |
| 251 | |
| 252 | RFC 4601: 4.3.1. Sending Hello Messages |
| 253 | |
| 254 | Thus, if a router needs to send a Join/Prune or Assert message on |
| 255 | an interface on which it has not yet sent a Hello message with the |
| 256 | currently configured IP address, then it MUST immediately send the |
| 257 | relevant Hello message without waiting for the Hello Timer to |
| 258 | expire, followed by the Join/Prune or Assert message. |
| 259 | |
| 260 | T30 DONE Run interface DR election when primary address changes |
| 261 | Reported by Andrew Lunn <andrew.lunn@ascom.ch> |
| 262 | See pim_if_dr_election(). |
| 263 | |
| 264 | T31 If an interface changes one of its secondary IP addresses, a Hello |
| 265 | message with an updated Address_List option and a non-zero |
| 266 | HoldTime should be sent immediately. |
| 267 | See also CAVEAT C15. |
| 268 | See also RFC 4601: 4.3.1. Sending Hello Messages |
| 269 | |
| 270 | T32 Detection of interface primary address changes may fail when there |
| 271 | are multiple addresses. |
| 272 | See also CAVEAT C14. |
| 273 | |
| 274 | pim_find_primary_addr() should return interface primary address |
| 275 | from connected list. Currently it returns the first address. |
| 276 | |
| 277 | Zebra daemon "show int" is able to keep the primary address as |
| 278 | first address. |
| 279 | |
| 280 | T33 DONE Implement debug command: test pim receive upcall |
| 281 | See also TODO T6: (S,G) Assert state machine. |
| 282 | |
| 283 | T34 DONE assert_action_a1 |
| 284 | |
| 285 | T35 DONE Review macros depending on interface I. |
| 286 | |
| 287 | See also: grep ,I\) pimd/*.c |
| 288 | |
| 289 | For the case (S,G,I) check if I is either |
| 290 | 1) interface attached to this per-interface S,G state (don't think so) |
| 291 | or |
| 292 | 2) an arbitrary interface (most probably) |
| 293 | |
| 294 | For the arbitrary interface case (2), consider representing |
| 295 | interface ifp as its primary address (struct in_addr ifaddr). The |
| 296 | benefit is in_addr does not need to be dereferenced, so it does |
| 297 | not demand protection against crashes. |
| 298 | |
| 299 | T36 DONE React to zebra daemon link-detect up/down notification. |
| 300 | pim_ifp->primary_address is managed by detect_primary_address_change() |
| 301 | depending on to ifp->connected (managed by zebra_interface_address_read()). |
| 302 | |
| 303 | T37 DONE Review list of variables which may affect pim_upstream.c |
| 304 | pim_upstream_evaluate_join_desired(). |
| 305 | Call pim_upstream_update_join_desired() accordingly. |
| 306 | |
| 307 | See the order of invokation: |
| 308 | pim_if_dr_election(ifp); |
| 309 | pim_if_update_join_desired(pim_ifp); /* depends on DR */ |
| 310 | pim_if_update_could_assert(ifp); /* depends on DR */ |
| 311 | pim_if_update_my_assert_metric(ifp); /* depends on could_assert */ |
| 312 | |
| 313 | join_desired depends on: |
| 314 | pim_ifp->primary_address |
| 315 | pim_ifp->pim_dr_addr |
| 316 | ch->ifassert_winner_metric |
| 317 | ch->ifassert_winner |
| 318 | ch->local_ifmembership |
| 319 | ch->ifjoin_state |
| 320 | ch->upstream->rpf.source_nexthop.mrib_metric_preference |
| 321 | ch->upstream->rpf.source_nexthop.mrib_route_metric |
| 322 | ch->upstream->rpf.source_nexthop.interface |
| 323 | |
| 324 | T38 DONE Detect change in AssertTrackingDesired(S,G,I) |
| 325 | |
| 326 | See the order of invokation: |
| 327 | dr_election: none |
| 328 | update_join_desired: depends on DR |
| 329 | update_tracking_desired: depends on DR, join_desired |
| 330 | |
| 331 | AssertTrackingDesired(S,G,I) depends on: |
| 332 | pim_ifp->primary_address |
| 333 | pim_ifp->pim_dr_addr |
| 334 | ch->local_ifmembership |
| 335 | ch->ifassert_winner |
| 336 | ch->ifjoin_state |
| 337 | ch->upstream->rpf.source_nexthop.interface |
| 338 | PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(ch->upstream->flags) |
| 339 | |
| 340 | T39 DONE AssertTrackingDesired: flags is not matching evaluation |
| 341 | |
| 342 | # show ip pim assert-internal |
| 343 | CA: CouldAssert |
| 344 | ECA: Evaluate CouldAssert |
| 345 | ATD: AssertTrackingDesired |
| 346 | eATD: Evaluate AssertTrackingDesired |
| 347 | |
| 348 | Interface Address Source Group CA eCA ATD eATD |
| 349 | eth0 192.168.1.100 1.1.1.1 239.1.1.1 no no no yes |
| 350 | # |
| 351 | |
| 352 | T40 Lightweight MLDv2 |
Everton Marques | ccc5d2b | 2009-10-02 14:50:08 -0300 | [diff] [blame] | 353 | http://tools.ietf.org/html/draft-ietf-mboned-lightweight-igmpv3-mldv2-05 |
Everton Marques | 871dbcf | 2009-08-11 15:43:05 -0300 | [diff] [blame] | 354 | http://www.ietf.org/internet-drafts/draft-ietf-mboned-lightweight-igmpv3-mldv2-05.txt |
| 355 | http://www.ietf.org/html.charters/mboned-charter.html |
| 356 | |
Everton Marques | e8c11bb | 2009-10-08 15:06:32 -0300 | [diff] [blame] | 357 | T41 DONE ssmping support |
Everton Marques | 3466dae | 2009-10-21 11:33:47 -0200 | [diff] [blame] | 358 | |
| 359 | See also: |
| 360 | http://www.venaas.no/multicast/ssmping/ |
| 361 | draft-ietf-mboned-ssmping-07 |
| 362 | http://tools.ietf.org/html/draft-ietf-mboned-ssmping-07 |
Everton Marques | e8c11bb | 2009-10-08 15:06:32 -0300 | [diff] [blame] | 363 | |
| 364 | Example: |
| 365 | |
| 366 | debug ssmpingd |
| 367 | |
| 368 | conf t |
| 369 | ip ssmpingd 1.1.1.1 |
| 370 | |
| 371 | show ip ssmpingd |
Everton Marques | 96f91ae | 2009-10-07 18:41:45 -0300 | [diff] [blame] | 372 | |
Everton Marques | 9986fb3 | 2010-02-22 09:09:09 -0300 | [diff] [blame] | 373 | T42 Static igmp join fails when loading config at boot time |
| 374 | |
| 375 | ! Wrong behavior seen at boot time: |
| 376 | ! |
| 377 | 2010/02/22 08:59:00 PIM: igmp_source_forward_start: ignoring request for |
| 378 | looped MFC entry (S,G)=(3.3.3.3,239.3.3.3): igmp_sock=12 oif=eth0 vif_index=2 |
| 379 | |
| 380 | ! Correct behavior seen later: |
| 381 | ! |
| 382 | 2010/02/22 09:03:16 PIM: igmp_source_forward_start: ignoring request for |
| 383 | looped MFC entry (S,G)=(2.2.2.2,239.2.2.2): igmp_sock=17 oif=lo vif_index=1 |
| 384 | |
| 385 | ! To see the wrong message at boot: |
| 386 | ! |
| 387 | debug igmp trace |
| 388 | ! |
| 389 | interface lo |
| 390 | ip igmp |
| 391 | ip igmp join 239.2.2.2 2.2.2.2 |
| 392 | ip igmp join 239.3.3.3 3.3.3.3 |
| 393 | ! |
| 394 | |
| 395 | ! Interfaces indexes: |
| 396 | Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut |
| 397 | eth0 200.202.112.3 2 2 0 0 0 0 |
| 398 | lo 127.0.0.1 1 1 0 0 0 0 |
| 399 | |
Everton Marques | 871dbcf | 2009-08-11 15:43:05 -0300 | [diff] [blame] | 400 | -x- |