Compare commits

...

6 Commits

Author SHA1 Message Date
Jan Vaclav
508d43efc9 gitlab-ci: add coverity submissions to weekly scheduled CI
We currently submit builds to Coverity manually every now and then,
but it would make sense to submit them more frequently and periodically,
so that it can detect defects sooner.

Add a "coverity" stage to the pipeline, which submits a build to Coverit
(the scheduls currently set to run every week).

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1973
2024-06-26 12:58:03 +02:00
Beniamino Galvani
14eaf4e419 merge: branch 'bg/netlink-strict-check'
Enable strict check on the netlink socket

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1962
2024-06-26 07:54:02 +00:00
Beniamino Galvani
185932a1a2 platform: enable strict check on netlink socket dumps
In the future we might want to specify filters when requesting netlink
dumps; this requires that strict check is enabled on the socket.

When enabling strict check, we need to pass a full struct in the
netlink message, otherwise kernel ignores it.

This commit doesn't change behavior.
2024-06-26 09:52:50 +02:00
Beniamino Galvani
2b8d8fe92a platform: don't set RTM_F_LOOKUP_TABLE for IPv6
RTM_F_LOOKUP_TABLE is only needed for IPv4. IPv6 dumps with the flag
are rejected in strict mode.
2024-06-26 09:52:50 +02:00
Beniamino Galvani
cac8c445e0 merge: branch 'feature/mstrodl/connectivity-timeout'
Add a timeout option to connectivity checks

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1968
2024-06-25 08:12:44 +00:00
Mary Strodl
ed318e8774 connectivity: Add a timeout option to connectivity checks
Adds an option in the connectivity section to change the timeout before
the interface is deemed "limited". Previously, it was hardcoded to
20 seconds, but for our usecase (failing over to cell modem if
hardwired ethernet drops), it's nice to be able to failover to another
interface more quickly.
2024-06-24 09:21:34 +00:00
15 changed files with 164 additions and 13 deletions

View File

@ -49,6 +49,7 @@ stages:
- tier3
- deploy
- triage
- coverity
variables:
FDO_UPSTREAM_REPO: NetworkManager/NetworkManager
@ -59,11 +60,11 @@ variables:
#
# This is done by running `ci-fairy generate-template` and possibly bumping
# ".default_tag".
ALPINE_TAG: 'tag-ec99bc32ed7f'
CENTOS_TAG: 'tag-a76c3f2e9d0f'
DEBIAN_TAG: 'tag-3f6892bcd503'
FEDORA_TAG: 'tag-a76c3f2e9d0f'
UBUNTU_TAG: 'tag-3f6892bcd503'
ALPINE_TAG: 'tag-f0b648c04526'
CENTOS_TAG: 'tag-c2d500e0391f'
DEBIAN_TAG: 'tag-7687baa06688'
FEDORA_TAG: 'tag-c2d500e0391f'
UBUNTU_TAG: 'tag-7687baa06688'
ALPINE_EXEC: 'bash .gitlab-ci/alpine-install.sh'
CENTOS_EXEC: 'bash .gitlab-ci/fedora-install.sh'
@ -639,6 +640,24 @@ triage:issues:
- gem install gitlab-triage
- gitlab-triage --debug --token $API_TOKEN --source-id $CI_PROJECT_ID
coverity:
extends:
- .fdo.distribution-image@fedora
variables:
FDO_DISTRIBUTION_VERSION: '40'
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
stage: coverity
needs: []
rules:
- if: $CI_PIPELINE_SOURCE == 'schedule'
script:
- dnf install -y curl
- BUILD_TYPE=meson CC=gcc CONFIGURE_ONLY=1 contrib/scripts/nm-ci-run.sh
- cd build
- ../.gitlab-ci/coverity.sh download
- cov-analysis-linux64-*/bin/cov-build --dir cov-int ninja
- ../.gitlab-ci/coverity.sh upload
# Clean the generated images periodically to get updated snapshots of the distribution images.
# Create an scheduled pipeline to run it, passing an AUTHFILE environment variable of type
# 'File' with an authentication token with API access level.

View File

@ -53,6 +53,7 @@ stages:
- tier3
- deploy
- triage
- coverity
variables:
FDO_UPSTREAM_REPO: NetworkManager/NetworkManager
@ -248,6 +249,24 @@ triage:issues:
- gem install gitlab-triage
- gitlab-triage --debug --token $API_TOKEN --source-id $CI_PROJECT_ID
coverity:
extends:
- .fdo.distribution-image@fedora
variables:
FDO_DISTRIBUTION_VERSION: '40'
FDO_DISTRIBUTION_TAG: $FEDORA_TAG
stage: coverity
needs: []
rules:
- if: $CI_PIPELINE_SOURCE == 'schedule'
script:
- dnf install -y curl
- BUILD_TYPE=meson CC=gcc CONFIGURE_ONLY=1 contrib/scripts/nm-ci-run.sh
- cd build
- ../.gitlab-ci/coverity.sh download
- cov-analysis-linux64-*/bin/cov-build --dir cov-int ninja
- ../.gitlab-ci/coverity.sh upload
# Clean the generated images periodically to get updated snapshots of the distribution images.
# Create an scheduled pipeline to run it, passing an AUTHFILE environment variable of type
# 'File' with an authentication token with API access level.

25
.gitlab-ci/coverity.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
set -e
[ "$COVERITY_SCAN_PROJECT_NAME" = "" ] && echo "missing COVERITY_SCAN_PROJECT_NAME" >&2 && exit 1
[ "$COVERITY_SCAN_TOKEN" = "" ] && echo "missing COVERITY_SCAN_PROJECT_NAME" >&2 && exit 1
if [ "$1" = "download" ]; then
curl https://scan.coverity.com/download/linux64 \
-o /tmp/cov-analysis-linux64.tar.gz \
--form "project=$COVERITY_SCAN_PROJECT_NAME" \
--form "token=$COVERITY_SCAN_TOKEN"
tar xvzf /tmp/cov-analysis-linux64.tar.gz
elif [ "$1" = "upload" ]; then
tar cvzf cov-int.tar.gz cov-int
ls -l cov-int.tar.gz
curl "https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME" \
--form "token=$COVERITY_SCAN_TOKEN" --form "email=$GITLAB_USER_EMAIL" \
--form file=@cov-int.tar.gz --form version="`meson introspect --projectinfo | jq -r .version`" \
--form description="ci run: $CI_COMMIT_TITLE / `git rev-parse --short HEAD`"
rm -rf cov-int*
else
echo "invalid command: $1" >&2
exit 1
fi

1
NEWS
View File

@ -9,6 +9,7 @@ the later release.
USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
* Support matching a OVS system interface by MAC address.
* Add a timeout option to connectivity checking.
=============================================
NetworkManager-1.48

View File

@ -1480,6 +1480,12 @@ managed=1
set to 0 connectivity checking is disabled. If missing, the
default is 300 seconds.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>timeout</varname></term>
<listitem><para>Specified in seconds; controls how long
to wait for a response before connectivity is marked as
limited. If missing, the default is 20 seconds.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>response</varname></term>
<listitem><para>If set, controls what body content

View File

@ -62,6 +62,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_CONFIG_MAIN_FILE,
PROP_CONNECTIVITY_ENABLED,
PROP_CONNECTIVITY_URI,
PROP_CONNECTIVITY_INTERVAL,
PROP_CONNECTIVITY_TIMEOUT,
PROP_CONNECTIVITY_RESPONSE,
PROP_NO_AUTO_DEFAULT, );
@ -86,6 +87,7 @@ typedef struct {
char *uri;
char *response;
guint interval;
guint timeout;
} connectivity;
int autoconnect_retries_default;
@ -304,6 +306,14 @@ nm_config_data_get_connectivity_interval(const NMConfigData *self)
return NM_CONFIG_DATA_GET_PRIVATE(self)->connectivity.interval;
}
guint
nm_config_data_get_connectivity_timeout(const NMConfigData *self)
{
g_return_val_if_fail(self, 0);
return NM_CONFIG_DATA_GET_PRIVATE(self)->connectivity.timeout;
}
const char *
nm_config_data_get_connectivity_response(const NMConfigData *self)
{
@ -2006,6 +2016,8 @@ nm_config_data_diff(NMConfigData *old_data, NMConfigData *new_data)
!= nm_config_data_get_connectivity_enabled(new_data)
|| nm_config_data_get_connectivity_interval(old_data)
!= nm_config_data_get_connectivity_interval(new_data)
|| nm_config_data_get_connectivity_timeout(old_data)
!= nm_config_data_get_connectivity_timeout(new_data)
|| !nm_streq0(nm_config_data_get_connectivity_uri(old_data),
nm_config_data_get_connectivity_uri(new_data))
|| !nm_streq0(nm_config_data_get_connectivity_response(old_data),
@ -2079,6 +2091,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
case PROP_CONNECTIVITY_INTERVAL:
g_value_set_uint(value, nm_config_data_get_connectivity_interval(self));
break;
case PROP_CONNECTIVITY_TIMEOUT:
g_value_set_uint(value, nm_config_data_get_connectivity_timeout(self));
break;
case PROP_CONNECTIVITY_RESPONSE:
g_value_set_string(value, nm_config_data_get_connectivity_response(self));
break;
@ -2221,6 +2236,15 @@ constructed(GObject *object)
NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL);
g_free(str);
/* On missing or invalid config value, fallback to 20. */
str = g_key_file_get_string(priv->keyfile,
NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY,
NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_TIMEOUT,
NULL);
priv->connectivity.timeout =
_nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXUINT, NM_CONFIG_DEFAULT_CONNECTIVITY_TIMEOUT);
g_free(str);
priv->dns_mode = nm_strstrip(g_key_file_get_string(priv->keyfile,
NM_CONFIG_KEYFILE_GROUP_MAIN,
NM_CONFIG_KEYFILE_KEY_MAIN_DNS,
@ -2420,6 +2444,15 @@ nm_config_data_class_init(NMConfigDataClass *config_class)
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_CONNECTIVITY_TIMEOUT] =
g_param_spec_uint(NM_CONFIG_DATA_CONNECTIVITY_TIMEOUT,
"",
"",
0,
G_MAXUINT,
0,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
obj_properties[PROP_CONNECTIVITY_RESPONSE] =
g_param_spec_string(NM_CONFIG_DATA_CONNECTIVITY_RESPONSE,
"",

View File

@ -47,6 +47,7 @@ typedef enum {
#define NM_CONFIG_DATA_CONNECTIVITY_ENABLED "connectivity-enabled"
#define NM_CONFIG_DATA_CONNECTIVITY_URI "connectivity-uri"
#define NM_CONFIG_DATA_CONNECTIVITY_INTERVAL "connectivity-interval"
#define NM_CONFIG_DATA_CONNECTIVITY_TIMEOUT "connectivity-timeout"
#define NM_CONFIG_DATA_CONNECTIVITY_RESPONSE "connectivity-response"
#define NM_CONFIG_DATA_NO_AUTO_DEFAULT "no-auto-default"
#define NM_CONFIG_DATA_DNS_MODE "dns"
@ -172,6 +173,7 @@ char **nm_config_data_get_plugins(const NMConfigData *config_data, gboolean
gboolean nm_config_data_get_connectivity_enabled(const NMConfigData *config_data);
const char *nm_config_data_get_connectivity_uri(const NMConfigData *config_data);
guint nm_config_data_get_connectivity_interval(const NMConfigData *config_data);
guint nm_config_data_get_connectivity_timeout(const NMConfigData *config_data);
const char *nm_config_data_get_connectivity_response(const NMConfigData *config_data);
int nm_config_data_get_autoconnect_retries_default(const NMConfigData *config_data);

View File

@ -871,6 +871,7 @@ static const ConfigGroup config_groups[] = {
.group = NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY,
.keys = NM_MAKE_STRV(NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_ENABLED,
NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_INTERVAL,
NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_TIMEOUT,
NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_RESPONSE,
NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_URI, ),
},

View File

@ -28,6 +28,7 @@
#define NM_CONFIG_SIGNAL_CONFIG_CHANGED "config-changed"
#define NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL 300
#define NM_CONFIG_DEFAULT_CONNECTIVITY_TIMEOUT 20
#define NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE "NetworkManager is online" /* NOT LOCALIZED */
typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions;

View File

@ -56,6 +56,7 @@ typedef struct {
char *host;
char *port;
char *response;
guint timeout;
} ConConfig;
struct _NMConnectivityCheckHandle {
@ -738,7 +739,9 @@ do_curl_request(NMConnectivityCheckHandle *cb_data, const char *hosts)
cb_data->concheck.curl_mhandle = mhandle;
cb_data->concheck.curl_ehandle = ehandle;
cb_data->concheck.request_headers = curl_slist_append(NULL, "Connection: close");
cb_data->timeout_source = nm_g_timeout_add_seconds_source(20, _timeout_cb, cb_data);
cb_data->timeout_source = nm_g_timeout_add_seconds_source(cb_data->concheck.con_config->timeout,
_timeout_cb,
cb_data);
curl_multi_setopt(mhandle, CURLMOPT_SOCKETFUNCTION, multi_socket_cb);
curl_multi_setopt(mhandle, CURLMOPT_SOCKETDATA, cb_data);
@ -1226,6 +1229,7 @@ update_config(NMConnectivity *self, NMConfigData *config_data)
{
NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE(self);
guint interval;
guint new_timeout;
gboolean enabled;
gboolean changed = FALSE;
const char *cur_uri = priv->con_config ? priv->con_config->uri : NULL;
@ -1237,6 +1241,8 @@ update_config(NMConnectivity *self, NMConfigData *config_data)
gs_free char *new_host = NULL;
gs_free char *new_port = NULL;
new_timeout = nm_config_data_get_connectivity_timeout(config_data);
new_uri = nm_config_data_get_connectivity_uri(config_data);
if (!nm_streq0(new_uri, cur_uri)) {
new_uri_valid = (new_uri && *new_uri);
@ -1277,6 +1283,7 @@ update_config(NMConnectivity *self, NMConfigData *config_data)
changed = TRUE;
if (!priv->con_config || !nm_streq0(new_uri, priv->con_config->uri)
|| new_timeout != priv->con_config->timeout
|| !nm_streq0(new_response, priv->con_config->response)) {
if (!new_host_port) {
new_host = priv->con_config ? g_strdup(priv->con_config->host) : NULL;
@ -1290,6 +1297,7 @@ update_config(NMConnectivity *self, NMConfigData *config_data)
.response = g_strdup(new_response),
.host = g_steal_pointer(&new_host),
.port = g_steal_pointer(&new_port),
.timeout = new_timeout,
};
}
priv->uri_valid = new_uri_valid;

View File

@ -9,6 +9,7 @@ level=INFO
[connectivity]
uri=http://example.com
interval=100
timeout=42
response=Hello
[extra-section]

View File

@ -167,6 +167,9 @@ test_config_simple(void)
g_assert_cmpint(nm_config_data_get_connectivity_interval(nm_config_get_data_orig(config)),
==,
100);
g_assert_cmpint(nm_config_data_get_connectivity_timeout(nm_config_get_data_orig(config)),
==,
42);
plugins = nm_config_data_get_plugins(nm_config_get_data_orig(config), FALSE);
g_assert_cmpint(g_strv_length((char **) plugins), ==, 3);

View File

@ -44,6 +44,7 @@
#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_ENABLED "enabled"
#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_INTERVAL "interval"
#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_TIMEOUT "timeout"
#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_RESPONSE "response"
#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_URI "uri"

View File

@ -337,6 +337,11 @@ struct _ifla_vf_vlan_info {
#define BRIDGE_VLAN_INFO_RANGE_END (1 << 4) /* VLAN is end of vlan range */
#endif
/* Appeared in kernel 4.2 dated August 2015 */
#ifndef RTM_F_LOOKUP_TABLE
#define RTM_F_LOOKUP_TABLE 0x1000 /* set rtm_table to FIB lookup result */
#endif
/*****************************************************************************/
#define PSCHED_TIME_UNITS_PER_SEC 1000000
@ -7784,17 +7789,42 @@ _nl_msg_new_dump_rtnl(NMPObjectType obj_type, int preferred_addr_family)
g_return_val_if_reached(NULL);
} break;
case NMP_OBJECT_TYPE_LINK:
{
struct ifinfomsg ifm = {};
if (nlmsg_append_struct(nlmsg, &ifm) < 0)
g_return_val_if_reached(NULL);
break;
}
case NMP_OBJECT_TYPE_IP4_ADDRESS:
case NMP_OBJECT_TYPE_IP6_ADDRESS:
case NMP_OBJECT_TYPE_IP4_ROUTE:
case NMP_OBJECT_TYPE_IP6_ROUTE:
case NMP_OBJECT_TYPE_ROUTING_RULE:
{
const struct rtgenmsg gmsg = {
.rtgen_family = preferred_addr_family,
struct ifaddrmsg ifm = {
.ifa_family = preferred_addr_family,
};
if (nlmsg_append_struct(nlmsg, &gmsg) < 0)
if (nlmsg_append_struct(nlmsg, &ifm) < 0)
g_return_val_if_reached(NULL);
break;
}
case NMP_OBJECT_TYPE_IP4_ROUTE:
case NMP_OBJECT_TYPE_IP6_ROUTE:
{
struct rtmsg rtm = {
.rtm_family = preferred_addr_family,
};
if (nlmsg_append_struct(nlmsg, &rtm) < 0)
g_return_val_if_reached(NULL);
break;
}
case NMP_OBJECT_TYPE_ROUTING_RULE:
{
struct fib_rule_hdr frh = {
.family = preferred_addr_family,
};
if (nlmsg_append_struct(nlmsg, &frh) < 0)
g_return_val_if_reached(NULL);
} break;
default:
@ -10307,7 +10337,7 @@ ip_route_get(NMPlatform *platform,
.r.rtm_family = addr_family,
.r.rtm_tos = 0,
.r.rtm_dst_len = IS_IPv4 ? 32 : 128,
.r.rtm_flags = 0x1000 /* RTM_F_LOOKUP_TABLE */,
.r.rtm_flags = IS_IPv4 ? RTM_F_LOOKUP_TABLE : 0,
};
nm_clear_pointer(&route, nmp_object_unref);

View File

@ -1152,6 +1152,7 @@ nl_socket_new(struct nl_sock **out_sk,
i_val = 1;
(void) setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_EXT_ACK, &i_val, sizeof(i_val));
(void) setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_GET_STRICT_CHK, &i_val, sizeof(i_val));
if (NM_FLAGS_HAS(flags, NL_SOCKET_FLAGS_PASSCRED)) {
err = nl_socket_set_passcred(sk, 1);