Skip to content

Commit a9f973b

Browse files
authored
Merge pull request #2571 from pqarmitage/updates
Enhance interface fault flags and resolve VRRP instances not leaving fault state and interface created
2 parents 3613636 + d5d2c36 commit a9f973b

File tree

13 files changed

+197
-133
lines changed

13 files changed

+197
-133
lines changed

configure.ac

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,8 @@ AC_ARG_ENABLE(malloc-check,
258258
[AS_HELP_STRING([--enable-malloc-check], [compile with malloc checking - i.e. malloc etc returning NULL])])
259259
AC_ARG_ENABLE(timer-check,
260260
[AS_HELP_STRING([--enable-timer-check], [compile with set time logging])])
261+
AC_ARG_ENABLE(fault-flags-check,
262+
[AS_HELP_STRING([--enable-fault-flags-check], [compile with checking VRRP fault flags])])
261263
AC_ARG_ENABLE(debug,
262264
[AS_HELP_STRING([--enable-debug], [compile with most debugging options])])
263265
AC_ARG_ENABLE(netlink-timers,
@@ -621,6 +623,7 @@ AS_IF([test .$enable_debug = .yes],
621623
AS_IF([test .$enable_checksum_debug = .], [enable_checksum_debug=yes])
622624
AS_IF([test .$enable_netlink_timers = .], [enable_netlink_timers=yes])
623625
AS_IF([test .$enable_network_timestamp = .], [enable_network_timestamp=yes])
626+
AS_IF([test .$enable_fault_flags_check = .], [enable_fault_flags_check=yes])
624627
])
625628
626629
AS_IF([test .$enable_lvs != .no],
@@ -2961,6 +2964,17 @@ if test "${enable_timer_check}" = "yes"; then
29612964
add_config_opt([TIMER_CHECK])
29622965
fi
29632966
2967+
AS_IF([test .$enable_vrrp != .no],
2968+
[
2969+
FAULT_FLAGS_CHECK=No
2970+
AS_IF([test .${enable_fault_flags_check} = .yes],
2971+
[
2972+
FAULT_FLAGS_CHECK=Yes
2973+
AC_DEFINE([_FAULT_FLAGS_CHECK_], [ 1 ], [Define to 1 to build with vrrp fault flag checking])
2974+
add_config_opt([FAULT_FLAGS_CHECK])
2975+
])
2976+
])
2977+
29642978
dnl ----[ Debug in one process or not ? ]----
29652979
if test "${enable_one_process_debug}" = yes; then
29662980
AC_DEFINE([_ONE_PROCESS_DEBUG_], [ 1 ], [Define to 1 to build with debugging support])
@@ -3641,6 +3655,8 @@ AS_IF([test ${OPENSSL_MEM_CHECK} = Yes],
36413655
if test ${TIMER_CHECK} = Yes; then
36423656
echo "Set time logging : Yes"
36433657
fi
3658+
AS_IF([test ${FAULT_FLAGS_CHECK} = Yes],
3659+
[echo "VRRP fault flags checks : Yes"])
36443660
if test ${ENABLE_DUMP_THREADS} = Yes; then
36453661
echo "Thread debugging : Yes"
36463662
fi

keepalived/check/libipvs.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,17 @@ static int ipvs_getinfo_parse_cb(struct nl_msg *msg, __attribute__((unused)) voi
385385
}
386386
#endif
387387

388-
static int ipvs_getinfo(bool retry)
388+
static int ipvs_getinfo(
389+
#ifndef LIBIPVS_USE_NL
390+
__attribute__((unused))
391+
#endif
392+
bool retry)
389393
{
390394
socklen_t len;
391395
struct ip_vs_getinfo ipvs_info;
396+
#ifdef LIBIPVS_USE_NL
392397
unsigned retries = retry ? 1 : 0;
398+
#endif
393399

394400
/* It appears that if we need to install the ip_vs module
395401
* (via keepalived_modprobe), then the first ipvs_nl_send_message()
@@ -431,7 +437,11 @@ static int ipvs_getinfo(bool retry)
431437
return getsockopt(sockfd, IPPROTO_IP, IP_VS_SO_GET_INFO, &ipvs_info, &len);
432438
}
433439

434-
int ipvs_init(bool retry)
440+
int ipvs_init(
441+
#ifndef LIBIPVS_USE_NL
442+
__attribute__((unused))
443+
#endif
444+
bool retry)
435445
{
436446
ipvs_func = ipvs_init;
437447

keepalived/core/keepalived_netlink.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,7 @@ netlink_if_address_filter(__attribute__((unused)) struct sockaddr_nl *snl, struc
10101010
vrrp->family == AF_INET ? VRRP_CONFIGURED_IFP(vrrp) :
10111011
#endif
10121012
vrrp->ifp) &&
1013-
(vrrp->num_track_fault || vrrp->flags_if_fault) &&
1013+
vrrp->flags_if_fault &&
10141014
vrrp->family == ifa->ifa_family &&
10151015
vrrp->saddr.ss_family == AF_UNSPEC &&
10161016
(!__test_bit(VRRP_FLAG_SADDR_FROM_CONFIG, &vrrp->flags) || is_tracking_saddr)) {
@@ -1019,7 +1019,7 @@ netlink_if_address_filter(__attribute__((unused)) struct sockaddr_nl *snl, struc
10191019
inet_ip4tosockaddr(addr.in, &vrrp->saddr);
10201020
else
10211021
inet_ip6tosockaddr(addr.in6, &vrrp->saddr);
1022-
try_up_instance(vrrp, false, false, VRRP_IF_FAULT_FLAG_NO_SOURCE_IP);
1022+
try_up_instance(vrrp, false, VRRP_FAULT_FL_NO_SOURCE_IP);
10231023
}
10241024
#ifdef _HAVE_VRRP_VMAC_
10251025
/* If IPv6 link local and vmac doesn't have an address or we have
@@ -1041,9 +1041,9 @@ netlink_if_address_filter(__attribute__((unused)) struct sockaddr_nl *snl, struc
10411041
* does not have one, then we will need the following code
10421042
*/
10431043
if (add_link_local_address(vrrp->ifp, addr.in6) &&
1044-
(vrrp->num_track_fault || vrrp->flags_if_fault) &&
1044+
vrrp->flags_if_fault &&
10451045
(!__test_bit(VRRP_FLAG_SADDR_FROM_CONFIG, &vrrp->flags) || is_tracking_saddr))
1046-
try_up_instance(vrrp, false, false, VRRP_IF_FAULT_FLAG_NO_SOURCE_IP);
1046+
try_up_instance(vrrp, false, VRRP_FAULT_FL_NO_SOURCE_IP);
10471047
} else
10481048
#endif
10491049
reset_link_local_address(&vrrp->ifp->sin6_addr, vrrp);
@@ -1167,7 +1167,7 @@ netlink_if_address_filter(__attribute__((unused)) struct sockaddr_nl *snl, struc
11671167
}
11681168
else if (IF_ISUP(ifp)) {
11691169
/* We failed to add an address, so down the instance */
1170-
down_instance(vrrp, false, VRRP_IF_FAULT_FLAG_NO_SOURCE_IP);
1170+
down_instance(vrrp, VRRP_FAULT_FL_NO_SOURCE_IP);
11711171
vrrp->saddr.ss_family = AF_UNSPEC;
11721172
}
11731173
}
@@ -1187,15 +1187,18 @@ netlink_if_address_filter(__attribute__((unused)) struct sockaddr_nl *snl, struc
11871187
IF_ISUP(ifp)) &&
11881188
#endif
11891189
(!__test_bit(VRRP_FLAG_SADDR_FROM_CONFIG, &vrrp->flags) || is_tracking_saddr)) {
1190-
/* Don't attempt to send an IPv6 advert if no address on the interface */
1190+
/* Don't attempt to send an IPv6 advert if no address on the interface, but we can
1191+
* for IPv4. So we want to clear the saddr before calling down_instance for IPv6,
1192+
* but after for IPv4.
1193+
*/
11911194
if (vrrp->saddr.ss_family == AF_INET6
11921195
#ifdef _HAVE_VRRP_VMAC_
11931196
&& !__test_bit(VRRP_VMAC_XMITBASE_BIT, &vrrp->flags)
11941197
#endif
11951198
)
11961199
vrrp->saddr.ss_family = AF_UNSPEC;
11971200

1198-
down_instance(vrrp, false, VRRP_IF_FAULT_FLAG_NO_SOURCE_IP);
1201+
down_instance(vrrp, VRRP_FAULT_FL_NO_SOURCE_IP);
11991202
vrrp->saddr.ss_family = AF_UNSPEC;
12001203
}
12011204
}
@@ -1605,19 +1608,21 @@ process_if_status_change(interface_t *ifp)
16051608
#ifdef _HAVE_VRRP_VMAC_
16061609
if (__test_bit(VRRP_VMAC_BIT, &vrrp->flags) &&
16071610
VRRP_CONFIGURED_IFP(vrrp) == ifp)
1608-
try_up_instance(vrrp, false, false, VRRP_IF_FAULT_FLAG_BASE_INTERFACE_DOWN);
1611+
try_up_instance(vrrp, false, VRRP_FAULT_FL_BASE_INTERFACE_DOWN);
16091612
else
16101613
#endif
1614+
{
16111615
/* assuming there is only one tracked interface per vrrp : to be checked */
1612-
try_up_instance(vrrp, false, false, VRRP_IF_FAULT_FLAG_INTERFACE_DOWN);
1616+
try_up_instance(vrrp, false, VRRP_FAULT_FL_INTERFACE_DOWN);
1617+
}
16131618
} else {
16141619
#ifdef _HAVE_VRRP_VMAC_
16151620
if (__test_bit(VRRP_VMAC_BIT, &vrrp->flags) &&
16161621
VRRP_CONFIGURED_IFP(vrrp) == ifp)
1617-
down_instance(vrrp, false, VRRP_IF_FAULT_FLAG_BASE_INTERFACE_DOWN);
1622+
down_instance(vrrp, VRRP_FAULT_FL_BASE_INTERFACE_DOWN);
16181623
else
16191624
#endif
1620-
down_instance(vrrp, false, VRRP_IF_FAULT_FLAG_INTERFACE_DOWN);
1625+
down_instance(vrrp, VRRP_FAULT_FL_INTERFACE_DOWN);
16211626
}
16221627
}
16231628
}
@@ -2214,7 +2219,6 @@ netlink_link_filter(__attribute__((unused)) struct sockaddr_nl *snl, struct nlms
22142219
if (strcmp(ifp->ifname, name)) {
22152220
/* The name can change, so handle that here */
22162221
log_message(LOG_INFO, "Interface name has changed from %s to %s", ifp->ifname, name);
2217-
22182222
#ifndef _ONE_PROCESS_DEBUG_
22192223
if (prog_type != PROG_TYPE_VRRP) {
22202224
ifp->ifi_flags = 0;

keepalived/include/vrrp.h

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -271,23 +271,16 @@ typedef struct _unicast_peer_t {
271271
list_head_t e_list;
272272
} unicast_peer_t;
273273

274-
275-
enum vrrp_if_fault_flags_bits {
276-
VRRP_IF_FAULT_FLAG_UNSPECIFIED = 0,
277-
VRRP_IF_FAULT_FLAG_INTERFACE_DOWN,
274+
typedef enum vrrp_fault_fl {
275+
VRRP_FAULT_FL_TRACKER = 0,
276+
VRRP_FAULT_FL_INTERFACE_DOWN,
278277
#ifdef _HAVE_VRRP_VMAC_
279-
VRRP_IF_FAULT_FLAG_BASE_INTERFACE_DOWN,
280-
VRRP_IF_FAULT_FLAG_DUPLICATE_VRID,
278+
VRRP_FAULT_FL_BASE_INTERFACE_DOWN,
281279
#endif /* _HAVE_VRRP_VMAC_ */
282-
VRRP_IF_FAULT_FLAG_NO_SOURCE_IP,
283-
VRRP_IF_FAULT_FLAG_CONFIG_ERROR,
284-
};
285-
286-
#define VRRP_IF_FAULT_INTERFACE_DOWN 0x1
287-
#ifdef _HAVE_VRRP_VMAC_
288-
#define VRRP_IF_FAULT_BASE_INTERFACE_DOWN 0x2
289-
#endif
290-
#define VRRP_IF_FAULT_DUPLICATE_VRID 0x4
280+
VRRP_FAULT_FL_DUPLICATE_VRID,
281+
VRRP_FAULT_FL_NO_SOURCE_IP,
282+
VRRP_FAULT_FL_CONFIG_ERROR,
283+
} vrrp_fault_fl_t;
291284

292285
/* parameters per virtual router -- rfc2338.6.1.2 */
293286
typedef struct _vrrp_t {
@@ -502,7 +495,7 @@ enum vrrp_packet_status {
502495
#endif
503496
#define VRRP_PKT_SADDR(V) (((V)->saddr.ss_family) ? ((struct sockaddr_in *) &(V)->saddr)->sin_addr.s_addr : IF_ADDR(VRRP_CONFIGURED_IFP(V)))
504497

505-
#define VRRP_ISUP(V) (!(V)->num_track_fault && !(V)->flags_if_fault)
498+
#define VRRP_ISUP(V) (!(V)->flags_if_fault)
506499

507500

508501
/* Configuration summary flags */

keepalived/include/vrrp_scheduler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ extern void vrrp_gratuitous_arp_vmac_update_thread(thread_ref_t);
7272
#endif
7373
extern void vrrp_arp_thread(thread_ref_t);
7474
extern void vrrp_gna_thread(thread_ref_t);
75-
extern void try_up_instance(vrrp_t *, bool, bool, enum vrrp_if_fault_flags_bits);
75+
extern void try_up_instance(vrrp_t *, bool, vrrp_fault_fl_t);
7676
#ifdef _WITH_DUMP_THREADS_
7777
extern void dump_threads(void);
7878
#endif

keepalived/include/vrrp_track.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ extern void alloc_track_bfd(const char *, list_head_t *, const vector_t *);
204204
#endif
205205
extern vrrp_script_t *find_script_by_name(const char *) __attribute__ ((pure));
206206
extern void update_script_priorities(vrrp_script_t *, bool);
207-
extern void down_instance(struct _vrrp_t *, bool, unsigned);
207+
extern void down_instance(struct _vrrp_t *, unsigned); // last param should be vrrp_fault_fl_t);
208208
extern void vrrp_set_effective_priority(struct _vrrp_t *);
209209
extern void initialise_tracking_priorities(void);
210210
#ifdef _WITH_TRACK_PROCESS_

keepalived/trackers/track_file.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ process_update_vrrp_track_file_status(const tracked_file_t *tfile, int new_statu
709709
, vrrp->iname, tfile->fname);
710710
if (top->weight)
711711
vrrp->total_priority -= previous_status;
712-
down_instance(vrrp, true, VRRP_IF_FAULT_FLAG_UNSPECIFIED);
712+
down_instance(vrrp, VRRP_FAULT_FL_TRACKER);
713713
} else if (previous_status == -254) {
714714
if (top->weight) {
715715
vrrp->total_priority += new_status;
@@ -722,7 +722,7 @@ process_update_vrrp_track_file_status(const tracked_file_t *tfile, int new_statu
722722
log_message(LOG_INFO, "(%s) Setting effective priority to %d"
723723
, vrrp->iname, vrrp->effective_priority);
724724
}
725-
try_up_instance(vrrp, false, true, VRRP_IF_FAULT_FLAG_UNSPECIFIED);
725+
try_up_instance(vrrp, false, VRRP_FAULT_FL_TRACKER);
726726
} else {
727727
vrrp->total_priority += new_status - previous_status;
728728
vrrp_set_effective_priority(vrrp);

keepalived/vrrp/vrrp.c

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,7 +1585,7 @@ vrrp_send_adv(vrrp_t * vrrp, uint8_t prio)
15851585
{
15861586
unicast_peer_t *peer;
15871587

1588-
if (!vrrp->sockets)
1588+
if (!vrrp->sockets || vrrp->sockets->fd_out == -1)
15891589
return;
15901590

15911591
#ifdef _HAVE_VRRP_VMAC_
@@ -2454,6 +2454,7 @@ add_vrrp_to_interface(vrrp_t *vrrp, interface_t *ifp, int weight, bool reverse,
24542454
{
24552455
char addr_str[INET6_ADDRSTRLEN];
24562456
tracking_obj_t *top = NULL;
2457+
track_t old_type;
24572458

24582459
if (list_empty(&ifp->tracking_vrrp)) {
24592460
if (log_addr && __test_bit(LOG_DETAIL_BIT, &debug)) {
@@ -2468,11 +2469,11 @@ add_vrrp_to_interface(vrrp_t *vrrp, interface_t *ifp, int weight, bool reverse,
24682469
, addr_str, ifp->ifname);
24692470
}
24702471
}
2471-
}
2472-
else if (type != TRACK_VRRP_DYNAMIC) {
2472+
} else {
24732473
/* Check if this is already in the list, and adjust the weight appropriately */
24742474
list_for_each_entry(top, &ifp->tracking_vrrp, e_list) {
24752475
if (top->obj.vrrp == vrrp) {
2476+
old_type = top->type;
24762477
if (top->type & (TRACK_VRRP | TRACK_IF | TRACK_SG) &&
24772478
type & (TRACK_VRRP | TRACK_IF | TRACK_SG) &&
24782479
top->weight != VRRP_NOT_TRACK_IF &&
@@ -2482,13 +2483,19 @@ add_vrrp_to_interface(vrrp_t *vrrp, interface_t *ifp, int weight, bool reverse,
24822483

24832484
/* Update the weight appropriately. We will use the sync group's
24842485
* weight unless the vrrp setting is unweighted. */
2485-
if (top->weight && weight != VRRP_NOT_TRACK_IF) {
2486+
if (type != TRACK_VRRP_DYNAMIC && top->weight && weight != VRRP_NOT_TRACK_IF) {
24862487
top->weight = weight;
24872488
top->weight_multiplier = reverse ? -1 : 1;
24882489
}
24892490

24902491
top->type |= type;
24912492

2493+
/* If we have set the dynamic bit, move top to head of list */
2494+
if (!(old_type & TRACK_VRRP_DYNAMIC) && type == TRACK_VRRP_DYNAMIC) {
2495+
list_del_init(&top->e_list);
2496+
list_head_add(&top->e_list, &ifp->tracking_vrrp);
2497+
}
2498+
24922499
return;
24932500
}
24942501
}
@@ -2508,9 +2515,6 @@ add_vrrp_to_interface(vrrp_t *vrrp, interface_t *ifp, int weight, bool reverse,
25082515
list_head_add(&top->e_list, &ifp->tracking_vrrp);
25092516
else
25102517
list_add_tail(&top->e_list, &ifp->tracking_vrrp);
2511-
2512-
/* if vrrp->num_if_script_fault needs incrementing, it will be
2513-
* done in initialise_tracking_priorities() */
25142518
}
25152519

25162520
void
@@ -2519,23 +2523,34 @@ del_vrrp_from_interface(vrrp_t *vrrp, interface_t *ifp)
25192523
tracking_obj_t *top, *top_tmp;
25202524

25212525
list_for_each_entry_safe(top, top_tmp, &ifp->tracking_vrrp, e_list) {
2522-
if (top->obj.vrrp == vrrp && top->type == TRACK_VRRP_DYNAMIC) {
2526+
if (top->obj.vrrp == vrrp && (top->type & TRACK_VRRP_DYNAMIC)) {
25232527
if (!IF_ISUP(ifp) && !__test_bit(VRRP_FLAG_DONT_TRACK_PRIMARY, &vrrp->flags)) {
25242528
#ifdef _HAVE_VRRP_VMAC_
2525-
if (__test_bit(VRRP_VMAC_BIT, &vrrp->flags) && VRRP_CONFIGURED_IFP(vrrp) == ifp)
2526-
__clear_bit(VRRP_IF_FAULT_FLAG_BASE_INTERFACE_DOWN, &vrrp->flags_if_fault);
2527-
else
2529+
if (__test_bit(VRRP_VMAC_BIT, &vrrp->flags) && VRRP_CONFIGURED_IFP(vrrp) == ifp)
2530+
__clear_bit(VRRP_FAULT_FL_BASE_INTERFACE_DOWN, &vrrp->flags_if_fault);
2531+
else
25282532
#endif
2533+
{
25292534
/* assuming there is only one tracked interface per vrrp : to be checked */
2530-
__clear_bit(VRRP_IF_FAULT_FLAG_INTERFACE_DOWN, &vrrp->flags_if_fault);
2535+
__clear_bit(VRRP_FAULT_FL_INTERFACE_DOWN, &vrrp->flags_if_fault);
2536+
}
25312537
}
2532-
free_tracking_obj(top);
2533-
break;
2538+
2539+
top->type &= ~TRACK_VRRP_DYNAMIC;
2540+
2541+
if (!top->type)
2542+
free_tracking_obj(top);
2543+
else {
2544+
list_del_init(&top->e_list);
2545+
list_add_tail(&top->e_list, &ifp->tracking_vrrp);
2546+
}
2547+
2548+
return;
25342549
}
25352550

25362551
/* The dynamic entries are at the start of the list */
2537-
if (top->type != TRACK_VRRP_DYNAMIC)
2538-
break;
2552+
if (!(top->type & TRACK_VRRP_DYNAMIC))
2553+
return;
25392554
}
25402555
}
25412556

@@ -2761,6 +2776,7 @@ open_sockpool_socket(sock_t *sock)
27612776
vrrp_t *vrrp;
27622777
sockaddr_t unicast_src;
27632778
const sockaddr_t *unicast_src_p = sock->unicast_src;
2779+
bool already_fault;
27642780

27652781
if (sock->unicast_src &&
27662782
sock->unicast_src->ss_family == AF_INET6 &&
@@ -2783,8 +2799,9 @@ open_sockpool_socket(sock_t *sock)
27832799
rb_for_each_entry(vrrp, &sock->rb_vrid, rb_vrid) {
27842800
if (vrrp->state != VRRP_STATE_FAULT)
27852801
log_message(LOG_INFO, "(%s): entering FAULT state (src address not configured)", vrrp->iname);
2786-
down_instance(vrrp, false, VRRP_IF_FAULT_FLAG_NO_SOURCE_IP);
2787-
if ((__num_bit(&vrrp->flags_if_fault) + vrrp->num_track_fault) == 1)
2802+
already_fault = vrrp->flags_if_fault;
2803+
down_instance(vrrp, VRRP_FAULT_FL_NO_SOURCE_IP);
2804+
if (!already_fault)
27882805
send_instance_notifies(vrrp);
27892806
}
27902807
sock->fd_in = -1;
@@ -4904,7 +4921,7 @@ vrrp_complete_init(void)
49044921
* We therefore need to clear num_track_fault and flags_if_fault here. */
49054922
list_for_each_entry(vrrp, &vrrp_data->vrrp, e_list) {
49064923
if (vrrp->num_config_faults)
4907-
__set_bit(VRRP_IF_FAULT_FLAG_CONFIG_ERROR, &vrrp->flags_if_fault);
4924+
__set_bit(VRRP_FAULT_FL_CONFIG_ERROR, &vrrp->flags_if_fault);
49084925
else {
49094926
vrrp->num_track_fault = 0;
49104927
vrrp->flags_if_fault = 0;

0 commit comments

Comments
 (0)