mirror_frr/pimd/pim_instance.h
saravanank ccf696e85f pimd: Do not allow to configure multicast on more than MAXVIF interfaces
RCA: When configured more than 32(MAXVIS), the inerfaces that are configured
after 32nd interfaces have the value of MAXVIF.
This is used as index to access the free vif tracker of array size 32(MAXVIFS).
So the channel oil list pointer which is present as the next field in pim structure get corrupt, when updating free vif.
This gets accessed during rpf update resulting in crash.

Fix: Refrain from allocating mcast interface structure and throw config error when more than MAXVIFS are attempted to configure.
Max vif checks are exempted for vrf device and pimreg as vrf device will be the first interface and not expected to fail and pimreg has reserved vif.
vxlan tunnel termination device creation has this check and throw warning on max vif.
All other creation are through CLI.

Signed-off-by: Saravanan K <saravanank@vmware.com>
2020-03-16 19:49:18 -07:00

211 lines
5.1 KiB
C

/*
* PIM for FRR - PIM Instance
* Copyright (C) 2017 Cumulus Networks, Inc.
* Donald Sharp
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef __PIM_INSTANCE_H__
#define __PIM_INSTANCE_H__
#include <mlag.h>
#include "pim_str.h"
#include "pim_msdp.h"
#include "pim_assert.h"
#include "pim_bsm.h"
#include "pim_vxlan_instance.h"
#include "pim_oil.h"
#include "pim_upstream.h"
#if defined(HAVE_LINUX_MROUTE_H)
#include <linux/mroute.h>
#else
/*
Below: from <linux/mroute.h>
*/
#ifndef MAXVIFS
#define MAXVIFS (256)
#endif
#endif
enum pim_spt_switchover {
PIM_SPT_IMMEDIATE,
PIM_SPT_INFINITY,
};
/* stats for updates rxed from the MLAG component during the life of a
* session
*/
struct pim_mlag_msg_stats {
uint32_t mroute_add_rx;
uint32_t mroute_add_tx;
uint32_t mroute_del_rx;
uint32_t mroute_del_tx;
uint32_t mlag_status_updates;
uint32_t pim_status_updates;
uint32_t vxlan_updates;
uint32_t peer_zebra_status_updates;
};
struct pim_mlag_stats {
/* message stats are reset when the connection to mlagd flaps */
struct pim_mlag_msg_stats msg;
uint32_t mlagd_session_downs;
uint32_t peer_session_downs;
uint32_t peer_zebra_downs;
};
enum pim_mlag_flags {
PIM_MLAGF_NONE = 0,
/* connection to the local MLAG daemon is up */
PIM_MLAGF_LOCAL_CONN_UP = (1 << 0),
/* connection to the MLAG daemon on the peer switch is up. note
* that there is no direct connection between FRR and the peer MLAG
* daemon. this is just a peer-session status provided by the local
* MLAG daemon.
*/
PIM_MLAGF_PEER_CONN_UP = (1 << 1),
/* status update rxed from the local daemon */
PIM_MLAGF_STATUS_RXED = (1 << 2),
/* initial dump of data done post peerlink flap */
PIM_MLAGF_PEER_REPLAY_DONE = (1 << 3),
/* zebra is up on the peer */
PIM_MLAGF_PEER_ZEBRA_UP = (1 << 4)
};
struct pim_router {
struct thread_master *master;
uint32_t debugs;
int t_periodic;
struct pim_assert_metric infinite_assert_metric;
long rpf_cache_refresh_delay_msec;
int32_t register_suppress_time;
int packet_process;
int32_t register_probe_time;
/*
* What is the default vrf that we work in
*/
vrf_id_t vrf_id;
enum mlag_role mlag_role;
uint32_t pim_mlag_intf_cnt;
/* if true we have registered with MLAG */
bool mlag_process_register;
/* if true local MLAG process reported that it is connected
* with the peer MLAG process
*/
bool connected_to_mlag;
/* Holds the client data(unencoded) that need to be pushed to MCLAGD*/
struct stream_fifo *mlag_fifo;
struct stream *mlag_stream;
struct thread *zpthread_mlag_write;
struct in_addr anycast_vtep_ip;
struct in_addr local_vtep_ip;
struct pim_mlag_stats mlag_stats;
enum pim_mlag_flags mlag_flags;
char peerlink_rif[INTERFACE_NAMSIZ];
struct interface *peerlink_rif_p;
};
/* Per VRF PIM DB */
struct pim_instance {
vrf_id_t vrf_id;
struct vrf *vrf;
struct {
enum pim_spt_switchover switchover;
char *plist;
} spt;
struct hash *rpf_hash;
void *ssm_info; /* per-vrf SSM configuration */
int send_v6_secondary;
struct thread *thread;
int mroute_socket;
int64_t mroute_socket_creation;
int64_t mroute_add_events;
int64_t mroute_add_last;
int64_t mroute_del_events;
int64_t mroute_del_last;
struct interface *regiface;
// List of static routes;
struct list *static_routes;
// Upstream vrf specific information
struct rb_pim_upstream_head upstream_head;
struct timer_wheel *upstream_sg_wheel;
/*
* RP information
*/
struct list *rp_list;
struct route_table *rp_table;
int iface_vif_index[MAXVIFS];
int mcast_if_count;
struct rb_pim_oil_head channel_oil_head;
struct pim_msdp msdp;
struct pim_vxlan_instance vxlan;
struct list *ssmpingd_list;
struct in_addr ssmpingd_group_addr;
unsigned int keep_alive_time;
unsigned int rp_keep_alive_time;
bool ecmp_enable;
bool ecmp_rebalance_enable;
/* No. of Dual active I/fs in pim_instance */
uint32_t inst_mlag_intf_cnt;
/* Bsm related */
struct bsm_scope global_scope;
uint64_t bsm_rcvd;
uint64_t bsm_sent;
uint64_t bsm_dropped;
/* If we need to rescan all our upstreams */
struct thread *rpf_cache_refresher;
int64_t rpf_cache_refresh_requests;
int64_t rpf_cache_refresh_events;
int64_t rpf_cache_refresh_last;
int64_t scan_oil_events;
int64_t scan_oil_last;
int64_t nexthop_lookups;
int64_t nexthop_lookups_avoided;
int64_t last_route_change_time;
};
void pim_vrf_init(void);
void pim_vrf_terminate(void);
struct pim_instance *pim_get_pim_instance(vrf_id_t vrf_id);
#endif