8 #include "pim_jp_agg.h"
10 #include "pim_iface.h"
13 pim_jp_agg_group_list_free (struct pim_jp_agg_group
*jag
)
15 list_delete(jag
->sources
);
17 XFREE (MTYPE_PIM_JP_AGG_GROUP
, jag
);
21 pim_jp_agg_src_free (struct pim_jp_sources
*js
)
24 * When we are being called here, we know
25 * that the neighbor is going away start
26 * the normal j/p timer so that it can
27 * pick this shit back up when the
28 * nbr comes back alive
30 join_timer_start(js
->up
);
31 XFREE (MTYPE_PIM_JP_AGG_SOURCE
, js
);
35 pim_jp_agg_group_list_cmp (void *arg1
, void *arg2
)
37 const struct pim_jp_agg_group
*jag1
= (const struct pim_jp_agg_group
*)arg1
;
38 const struct pim_jp_agg_group
*jag2
= (const struct pim_jp_agg_group
*)arg2
;
40 if (jag1
->group
.s_addr
< jag2
->group
.s_addr
)
43 if (jag1
->group
.s_addr
> jag2
->group
.s_addr
)
50 pim_jp_agg_src_cmp (void *arg1
, void *arg2
)
52 const struct pim_jp_sources
*js1
= (const struct pim_jp_sources
*)arg1
;
53 const struct pim_jp_sources
*js2
= (const struct pim_jp_sources
*)arg2
;
55 if (js1
->up
->sg
.src
.s_addr
< js2
->up
->sg
.src
.s_addr
)
58 if (js1
->up
->sg
.src
.s_addr
> js2
->up
->sg
.src
.s_addr
)
65 pim_jp_agg_clear_group (struct list
*group
)
67 struct listnode
*node
, *nnode
;
68 struct pim_jp_agg_group
*jag
;
70 for (ALL_LIST_ELEMENTS(group
, node
, nnode
, jag
))
72 list_delete(jag
->sources
);
74 listnode_delete(group
, jag
);
75 XFREE(MTYPE_PIM_JP_AGG_GROUP
, jag
);
79 static struct pim_iface_upstream_switch
*
80 pim_jp_agg_get_interface_upstream_switch_list (struct pim_rpf
*rpf
)
82 struct pim_interface
*pim_ifp
= rpf
->source_nexthop
.interface
->info
;
83 struct pim_iface_upstream_switch
*pius
;
84 struct listnode
*node
, *nnode
;
86 for (ALL_LIST_ELEMENTS(pim_ifp
->upstream_switch_list
, node
, nnode
, pius
))
88 if (pius
->address
.s_addr
== rpf
->rpf_addr
.u
.prefix4
.s_addr
)
94 pius
= XCALLOC(MTYPE_PIM_JP_AGG_GROUP
, sizeof (struct pim_iface_upstream_switch
));
95 pius
->address
.s_addr
= rpf
->rpf_addr
.u
.prefix4
.s_addr
;
96 pius
->us
= list_new();
97 listnode_add (pim_ifp
->upstream_switch_list
, pius
);
104 pim_jp_agg_remove_group (struct list
*group
, struct pim_upstream
*up
)
106 struct listnode
*node
, *nnode
;
107 struct pim_jp_agg_group
*jag
= NULL
;
108 struct pim_jp_sources
*js
= NULL
;
110 for (ALL_LIST_ELEMENTS(group
, node
, nnode
, jag
))
112 if (jag
->group
.s_addr
== up
->sg
.grp
.s_addr
)
119 for (ALL_LIST_ELEMENTS(jag
->sources
, node
, nnode
, js
))
125 listnode_delete(jag
->sources
, js
);
127 XFREE(MTYPE_PIM_JP_AGG_SOURCE
, js
);
129 if (jag
->sources
->count
== 0)
131 list_delete(jag
->sources
);
132 listnode_delete(group
, jag
);
137 pim_jp_agg_add_group (struct list
*group
, struct pim_upstream
*up
, bool is_join
)
139 struct listnode
*node
, *nnode
;
140 struct pim_jp_agg_group
*jag
= NULL
;
141 struct pim_jp_sources
*js
;
143 for (ALL_LIST_ELEMENTS(group
, node
, nnode
, jag
))
145 if (jag
->group
.s_addr
== up
->sg
.grp
.s_addr
)
151 jag
= XCALLOC(MTYPE_PIM_JP_AGG_GROUP
, sizeof (struct pim_jp_agg_group
));
152 jag
->group
.s_addr
= up
->sg
.grp
.s_addr
;
153 jag
->sources
= list_new();
154 jag
->sources
->cmp
= pim_jp_agg_src_cmp
;
155 jag
->sources
->del
= (void (*)(void *))pim_jp_agg_src_free
;
156 listnode_add (group
, jag
);
159 js
= XCALLOC(MTYPE_PIM_JP_AGG_SOURCE
, sizeof (struct pim_jp_sources
));
161 js
->is_join
= is_join
;
163 listnode_add (jag
->sources
, js
);
167 pim_jp_agg_switch_interface (struct pim_rpf
*orpf
,
168 struct pim_rpf
*nrpf
,
169 struct pim_upstream
*up
)
171 struct pim_iface_upstream_switch
*opius
;
172 struct pim_iface_upstream_switch
*npius
;
174 opius
= pim_jp_agg_get_interface_upstream_switch_list(orpf
);
175 npius
= pim_jp_agg_get_interface_upstream_switch_list(nrpf
);
178 * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages
180 * Transitions from Joined State
182 * RPF'(S,G) changes not due to an Assert
184 * The upstream (S,G) state machine remains in Joined
185 * state. Send Join(S,G) to the new upstream neighbor, which is
186 * the new value of RPF'(S,G). Send Prune(S,G) to the old
187 * upstream neighbor, which is the old value of RPF'(S,G). Set
188 * the Join Timer (JT) to expire after t_periodic seconds.
191 /* send Prune(S,G) to the old upstream neighbor */
192 pim_jp_agg_add_group (opius
->us
, up
, false);
194 /* send Join(S,G) to the current upstream neighbor */
195 pim_jp_agg_add_group (npius
->us
, up
, true);
201 pim_jp_agg_single_upstream_send (struct pim_rpf
*rpf
,
202 struct pim_upstream
*up
,
205 static struct list
*groups
= NULL
;
206 static struct pim_jp_agg_group jag
;
207 static struct pim_jp_sources js
;
209 static bool first
= true;
215 jag
.sources
= list_new();
217 listnode_add(groups
, &jag
);
218 listnode_add(jag
.sources
, &js
);
223 jag
.group
.s_addr
= up
->sg
.grp
.s_addr
;
225 js
.is_join
= is_join
;
227 pim_joinprune_send(rpf
, groups
);