inverts the meaning (i.e. the rule only applies to packets that don't match
the mark).
+charon.plugins.kernel-netlink.hw_offload_feature_interface = lo
+ Interface to be used to find hardware offload feature flag on.
+
+ If the kernel supports hardware offloading, the plugin needs to find the
+ feature flag which represents hardware offloading support for network
+ devices. Using the loopback device for this purpose is usually fine, since
+ it should always be present. For rare cases in which the loopback device
+ cannot be used to obtain the appropriate feature flag, this option can
+ be used to specify an alternative interface for offload feature detection.
+
charon.plugins.kernel-netlink.mss = 0
MSS to set on installed routes, 0 to disable.
* ETHTOOL_GFEATURES since 2.6.39, so check for the latter */
#ifdef ETHTOOL_GFEATURES
-/**
- * IPsec HW offload state in kernel
- */
-typedef enum {
- NL_OFFLOAD_UNKNOWN,
- NL_OFFLOAD_UNSUPPORTED,
- NL_OFFLOAD_SUPPORTED
-} nl_offload_state_t;
-
/**
* Global metadata used for IPsec HW offload
*/
static struct {
+ /** determined HW offload support */
+ bool supported;
/** bit in feature set */
u_int bit;
/** total number of device feature blocks */
u_int total_blocks;
- /** determined HW offload state */
- nl_offload_state_t state;
} netlink_hw_offload;
/**
- * Check if kernel supports HW offload
+ * Check if kernel supports HW offload and determine feature flag
*/
-static void netlink_find_offload_feature(const char *ifname, int query_socket)
+static void netlink_find_offload_feature(const char *ifname)
{
struct ethtool_sset_info *sset_info;
struct ethtool_gstrings *cmd = NULL;
struct ifreq ifr;
uint32_t sset_len, i;
char *str;
- int err;
+ int err, query_socket;
- netlink_hw_offload.state = NL_OFFLOAD_UNSUPPORTED;
+ query_socket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM);
+ if (query_socket < 0)
+ {
+ return;
+ }
/* determine number of device features */
INIT_EXTRA(sset_info, sizeof(uint32_t),
{
if (strneq(str, "esp-hw-offload", ETH_GSTRING_LEN))
{
+ netlink_hw_offload.supported = TRUE;
netlink_hw_offload.bit = i;
netlink_hw_offload.total_blocks = (sset_len + 31) / 32;
- netlink_hw_offload.state = NL_OFFLOAD_SUPPORTED;
break;
}
str += ETH_GSTRING_LEN;
out:
free(sset_info);
free(cmd);
+ close(query_socket);
}
/**
int block;
bool ret = FALSE;
- query_socket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM);
- if (query_socket < 0)
+ if (!netlink_hw_offload.supported)
{
+ DBG1(DBG_KNL, "HW offload is not supported by kernel");
return FALSE;
}
- /* kernel requires a real interface in order to query the kernel-wide
- * capability, so we do it here on first invocation.
- */
- if (netlink_hw_offload.state == NL_OFFLOAD_UNKNOWN)
- {
- netlink_find_offload_feature(ifname, query_socket);
- }
- if (netlink_hw_offload.state == NL_OFFLOAD_UNSUPPORTED)
+ query_socket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_XFRM);
+ if (query_socket < 0)
{
- DBG1(DBG_KNL, "HW offload is not supported by kernel");
- goto out;
+ return FALSE;
}
/* feature is supported by kernel, query device features */
ifr.ifr_name[IFNAMSIZ-1] = '\0';
ifr.ifr_data = (void*)cmd;
- if (ioctl(query_socket, SIOCETHTOOL, &ifr))
+ if (!ioctl(query_socket, SIOCETHTOOL, &ifr))
{
- goto out_free;
- }
-
- block = netlink_hw_offload.bit / 32;
- feature_bit = 1U << (netlink_hw_offload.bit % 32);
- if (cmd->features[block].active & feature_bit)
- {
- ret = TRUE;
+ block = netlink_hw_offload.bit / 32;
+ feature_bit = 1U << (netlink_hw_offload.bit % 32);
+ if (cmd->features[block].active & feature_bit)
+ {
+ ret = TRUE;
+ }
}
-out_free:
- free(cmd);
if (!ret)
{
DBG1(DBG_KNL, "HW offload is not supported by device");
}
-out:
+ free(cmd);
close(query_socket);
return ret;
}
#else
+static void netlink_find_offload_feature(const char *ifname)
+{
+}
+
static bool netlink_detect_offload(const char *ifname)
{
return FALSE;
(watcher_cb_t)receive_events, this);
}
+ netlink_find_offload_feature(lib->settings->get_str(lib->settings,
+ "%s.hw_offload_feature_interface", "lo",
+ lib->ns));
+
return &this->public;
}