1 /* 2 * IP MSDP for Quagga 3 * Copyright (C) 2016 Cumulus Networks, Inc. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; see the file COPYING; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 #ifndef PIM_MSDP_H 20 #define PIM_MSDP_H 21 22 enum pim_msdp_peer_state { 23 PIM_MSDP_DISABLED, 24 PIM_MSDP_INACTIVE, 25 PIM_MSDP_LISTEN, 26 PIM_MSDP_CONNECTING, 27 PIM_MSDP_ESTABLISHED 28 }; 29 30 /* SA and KA TLVs are processed; rest ignored */ 31 enum pim_msdp_tlv { 32 PIM_MSDP_V4_SOURCE_ACTIVE = 1, 33 PIM_MSDP_V4_SOURCE_ACTIVE_REQUEST, 34 PIM_MSDP_V4_SOURCE_ACTIVE_RESPONSE, 35 PIM_MSDP_KEEPALIVE, 36 PIM_MSDP_RESERVED, 37 PIM_MSDP_TRACEROUTE_PROGRESS, 38 PIM_MSDP_TRACEROUTE_REPLY, 39 }; 40 41 /* MSDP error codes */ 42 enum pim_msdp_err { 43 PIM_MSDP_ERR_NONE = 0, 44 PIM_MSDP_ERR_OOM = -1, 45 PIM_MSDP_ERR_PEER_EXISTS = -2, 46 PIM_MSDP_ERR_MAX_MESH_GROUPS = -3, 47 PIM_MSDP_ERR_NO_PEER = -4, 48 PIM_MSDP_ERR_MG_MBR_EXISTS = -5, 49 PIM_MSDP_ERR_NO_MG = -6, 50 PIM_MSDP_ERR_NO_MG_MBR = -7, 51 PIM_MSDP_ERR_SIP_EQ_DIP = -8, 52 }; 53 54 #define PIM_MSDP_STATE_STRLEN 16 55 #define PIM_MSDP_UPTIME_STRLEN 80 56 #define PIM_MSDP_TIMER_STRLEN 12 57 #define PIM_MSDP_TCP_PORT 639 58 #define PIM_MSDP_SOCKET_SNDBUF_SIZE 65536 59 60 enum pim_msdp_sa_flags { 61 PIM_MSDP_SAF_NONE = 0, 62 /* There are two cases where we can pickup an active source locally - 63 * 1. We are RP and got a source-register from the FHR 64 * 2. We are RP and FHR and learnt a new directly connected source on a 65 * DR interface */ 66 PIM_MSDP_SAF_LOCAL = (1 << 0), 67 /* We got this in the MSDP SA TLV from a peer (and this passed peer-RPF 68 * checks) */ 69 PIM_MSDP_SAF_PEER = (1 << 1), 70 PIM_MSDP_SAF_REF = (PIM_MSDP_SAF_LOCAL | PIM_MSDP_SAF_PEER), 71 PIM_MSDP_SAF_STALE = (1 << 2), /* local entries can get kicked out on 72 * misc pim events such as RP change */ 73 PIM_MSDP_SAF_UP_DEL_IN_PROG = (1 << 3) 74 }; 75 76 struct pim_msdp_sa { 77 struct pim_instance *pim; 78 79 struct prefix_sg sg; 80 char sg_str[PIM_SG_LEN]; 81 struct in_addr rp; /* Last RP address associated with this SA */ 82 struct in_addr peer; /* last peer from who we heard this SA */ 83 enum pim_msdp_sa_flags flags; 84 85 /* rfc-3618 is missing default value for SA-hold-down-Period. pulled 86 * this number from industry-standards */ 87 #define PIM_MSDP_SA_HOLD_TIME ((3*60)+30) 88 struct thread *sa_state_timer; // 5.6 89 int64_t uptime; 90 91 struct pim_upstream *up; 92 }; 93 94 enum pim_msdp_peer_flags { 95 PIM_MSDP_PEERF_NONE = 0, 96 PIM_MSDP_PEERF_LISTENER = (1 << 0), 97 #define PIM_MSDP_PEER_IS_LISTENER(mp) (mp->flags & PIM_MSDP_PEERF_LISTENER) 98 PIM_MSDP_PEERF_SA_JUST_SENT = (1 << 1) 99 }; 100 101 struct pim_msdp_peer { 102 struct pim_instance *pim; 103 104 /* configuration */ 105 struct in_addr local; 106 struct in_addr peer; 107 char *mesh_group_name; 108 char key_str[INET_ADDRSTRLEN]; 109 110 /* state */ 111 enum pim_msdp_peer_state state; 112 enum pim_msdp_peer_flags flags; 113 114 /* TCP socket info */ 115 union sockunion su_local; 116 union sockunion su_peer; 117 int fd; 118 119 /* protocol timers */ 120 #define PIM_MSDP_PEER_HOLD_TIME 75 121 struct thread *hold_timer; // 5.4 122 #define PIM_MSDP_PEER_KA_TIME 60 123 struct thread *ka_timer; // 5.5 124 #define PIM_MSDP_PEER_CONNECT_RETRY_TIME 30 125 struct thread *cr_timer; // 5.6 126 127 /* packet thread and buffers */ 128 uint32_t packet_size; 129 struct stream *ibuf; 130 struct stream_fifo *obuf; 131 struct thread *t_read; 132 struct thread *t_write; 133 134 /* stats */ 135 uint32_t conn_attempts; 136 uint32_t est_flaps; 137 uint32_t sa_cnt; /* number of SAs attributed to this peer */ 138 #define PIM_MSDP_PEER_LAST_RESET_STR 20 139 char last_reset[PIM_MSDP_PEER_LAST_RESET_STR]; 140 141 /* packet stats */ 142 uint32_t ka_tx_cnt; 143 uint32_t sa_tx_cnt; 144 uint32_t ka_rx_cnt; 145 uint32_t sa_rx_cnt; 146 uint32_t unk_rx_cnt; 147 148 /* timestamps */ 149 int64_t uptime; 150 }; 151 152 struct pim_msdp_mg_mbr { 153 struct in_addr mbr_ip; 154 struct pim_msdp_peer *mp; 155 }; 156 157 /* PIM MSDP mesh-group */ 158 struct pim_msdp_mg { 159 char *mesh_group_name; 160 struct in_addr src_ip; 161 uint32_t mbr_cnt; 162 struct list *mbr_list; 163 }; 164 165 enum pim_msdp_flags { 166 PIM_MSDPF_NONE = 0, 167 PIM_MSDPF_ENABLE = (1 << 0), 168 PIM_MSDPF_LISTENER = (1 << 1) 169 }; 170 171 struct pim_msdp_listener { 172 int fd; 173 union sockunion su; 174 struct thread *thread; 175 }; 176 177 struct pim_msdp { 178 enum pim_msdp_flags flags; 179 struct thread_master *master; 180 struct pim_msdp_listener listener; 181 uint32_t rejected_accepts; 182 183 /* MSDP peer info */ 184 struct hash *peer_hash; 185 struct list *peer_list; 186 187 /* MSDP active-source info */ 188 #define PIM_MSDP_SA_ADVERTISMENT_TIME 60 189 struct thread *sa_adv_timer; // 5.6 190 struct hash *sa_hash; 191 struct list *sa_list; 192 uint32_t local_cnt; 193 194 /* keep a scratch pad for building SA TLVs */ 195 struct stream *work_obuf; 196 197 struct in_addr originator_id; 198 199 /* currently only one mesh-group is supported - so just stash it here */ 200 struct pim_msdp_mg *mg; 201 }; 202 203 #define PIM_MSDP_PEER_READ_ON(mp) \ 204 thread_add_read(mp->pim->msdp.master, pim_msdp_read, mp, mp->fd, \ 205 &mp->t_read) 206 207 #define PIM_MSDP_PEER_WRITE_ON(mp) \ 208 thread_add_write(mp->pim->msdp.master, pim_msdp_write, mp, mp->fd, \ 209 &mp->t_write) 210 211 #define PIM_MSDP_PEER_READ_OFF(mp) THREAD_READ_OFF(mp->t_read) 212 #define PIM_MSDP_PEER_WRITE_OFF(mp) THREAD_WRITE_OFF(mp->t_write) 213 214 // struct pim_msdp *msdp; 215 struct pim_instance; 216 void pim_msdp_init(struct pim_instance *pim, struct thread_master *master); 217 void pim_msdp_exit(struct pim_instance *pim); 218 enum pim_msdp_err pim_msdp_peer_add(struct pim_instance *pim, 219 struct in_addr peer, struct in_addr local, 220 const char *mesh_group_name, 221 struct pim_msdp_peer **mp_p); 222 enum pim_msdp_err pim_msdp_peer_del(struct pim_instance *pim, 223 struct in_addr peer_addr); 224 char *pim_msdp_state_dump(enum pim_msdp_peer_state state, char *buf, 225 int buf_size); 226 struct pim_msdp_peer *pim_msdp_peer_find(struct pim_instance *pim, 227 struct in_addr peer_addr); 228 void pim_msdp_peer_established(struct pim_msdp_peer *mp); 229 void pim_msdp_peer_pkt_rxed(struct pim_msdp_peer *mp); 230 void pim_msdp_peer_stop_tcp_conn(struct pim_msdp_peer *mp, bool chg_state); 231 void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str); 232 int pim_msdp_write(struct thread *thread); 233 char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size, 234 bool long_format); 235 int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty, 236 const char *spaces); 237 void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp); 238 void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp, 239 struct prefix_sg *sg, struct in_addr rp); 240 void pim_msdp_sa_local_update(struct pim_upstream *up); 241 void pim_msdp_sa_local_del(struct pim_instance *pim, struct prefix_sg *sg); 242 void pim_msdp_i_am_rp_changed(struct pim_instance *pim); 243 bool pim_msdp_peer_rpf_check(struct pim_msdp_peer *mp, struct in_addr rp); 244 void pim_msdp_up_join_state_changed(struct pim_instance *pim, 245 struct pim_upstream *xg_up); 246 void pim_msdp_up_del(struct pim_instance *pim, struct prefix_sg *sg); 247 enum pim_msdp_err pim_msdp_mg_mbr_add(struct pim_instance *pim, 248 const char *mesh_group_name, 249 struct in_addr mbr_ip); 250 enum pim_msdp_err pim_msdp_mg_mbr_del(struct pim_instance *pim, 251 const char *mesh_group_name, 252 struct in_addr mbr_ip); 253 enum pim_msdp_err pim_msdp_mg_src_del(struct pim_instance *pim, 254 const char *mesh_group_name); 255 enum pim_msdp_err pim_msdp_mg_src_add(struct pim_instance *pim, 256 const char *mesh_group_name, 257 struct in_addr src_ip); 258 enum pim_msdp_err pim_msdp_mg_del(struct pim_instance *pim, 259 const char *mesh_group_name); 260 #endif 261