Failover with CARP in PF: Part Three (Checking for CARP & pfsync)

In the previous two articles in this series, I mentioned some of the advantages of using CARP and outlined a hypothetical CARP implementation involving two redundant firewalls. In this article, I will take it one step further and discuss how to configure the firewalls, starting by making sure your flavor of BSD has both CARP and pfsync enabled.

Making Sure CARP and pfsync Are Enabled


Checking the value of the net.inet.carp variables at the command prompt in FreeBSD.

If you are setting this up on a pfSense box, then both the carp and pfsync devices should be compiled into the kernel. But if it isn’t, and you are running FreeBSD, then you need to check that the kernel has both these devices are compiled in. You can check for CARP with the following command:

sysctl net.inet.carp.allow

If you see:


then your system comes equipped with CARP. If, however, you see something like:

sysctl: unknown old ‘net.inet.carp.allow’

then your kernel is not configured for CARP.

If you are running OpenBSD or NetBSD, you should heed the following regarding CARP and pfsync:

  • OpenBSD: Both carp and pfsync devices are in the default GENERIC and kernel configurations, so unless you are running a custom kernel, you should be OK.
  • NetBSD: NetBSD’s default generic kernel does not have CARP compiled in, and NetBSD does not yet support pfsync.

There are actually four CARP-related variables: net.inet.carp.allow, net.inet.carp.preempt, net.inet.carp.suppress_preempt, net.inet.carp.log, and net.inet.carp.arpbalance. Setting net.inet.carp.log to 1 gives you debug information about the CARP traffic you logged, but this is turned off by default. The inet.carp.arpbalance command load balances local network traffic using ARP. net.inet.carp.suppress_preempt is a read-only variable showing the status of preemption suppression. Preemption can be suppressed if the link on an interface is down. A value of 0 means that preemption is not suppressed. Every problem increments this variable.

The important variables are net.inet.carp.allow and net.inet.carp.preempt. Setting net.inet.carp.allow to 1 allows the system to accept incoming CARP packets (this option is enabled by default). For graceful failover between the gateways in our hypothetical network, we need to set the net.inet.carp.preempt variable to 1. Setting the net.inet.carp.preempt variable means that on hosts with more than one network interface, all CARP interfaces will set their advskew to the extremely high value of 240 in order to prod other hosts in the CARP group to start failover when one of the interfaces goes down. This setting needs to be identical on all hosts in the CARP group, so you need to repeat the setting on all hosts.

Creating the CARP Interfaces

Once we’re sure both CARP and pfsync are enabled, we want to set up the network interfaces. In part two, I specified that the external CARP interface (carp0) would have an IP of, and the internal CARP interface (carp1) would have an IP address of

We first create the interfaces using ifconfig:

ifconfig carp0 vhid 1
ifconfig carp1 vhid 2

Here we do not need to set the physical interface explicitly The cp0 and cp1 virtual interfaces here will bind themselves to the physical interfaces that are already configured with addresses in the same subnets as the assigned CARP address. with ifconfig you should be able to check that each CARP interface is properly configured.

On the backup firewall, the ifconfig command is similar, except that you add the advskew parameter:

ifconfig carp0 vhid 1 advskew 100
ifconfig carp1 vhid 2 advskew 100

The advskew parameter indicates how much less preferred it is for the specified machine to take over for the current master. In this case, the master will announce every second (1 + 0/256), while the backup will wait for 1 + 100/256 seconds. Since we set net.inet.carp.preempt to 1, when the master stops announcing or announces it is not available, the backups will take over. Smaller advskew values mean shorter announcement intervals and higher likelihood for becoming the new master.

In the next article in this series, I will continue with configuration of our hypothetical CARP setup.


In Part Two of this series, I erroneously referred to the CARP interfaces as cp0 and cp1. They need to be carp0 and carp1. This has been corrected. I apologize for any inconvenience.

External Links:

Common Address Redundancy Protocol (CARP) at – a section from the FreeBSD handbook.

Be Sociable, Share!

Speak Your Mind


© 2013 David Zientara. All rights reserved. Privacy Policy