diff --git a/clients/cli/connections.c b/clients/cli/connections.c index e5fa81b814..31b01d4912 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -120,6 +120,7 @@ extern NmcOutputField nmc_fields_setting_dcb[]; extern NmcOutputField nmc_fields_setting_tun[]; extern NmcOutputField nmc_fields_setting_ip_tunnel[]; extern NmcOutputField nmc_fields_setting_macvlan[]; +extern NmcOutputField nmc_fields_setting_vxlan[]; /* Available settings for 'connection show ' - profile part */ static NmcOutputField nmc_fields_settings_names[] = { @@ -151,6 +152,7 @@ static NmcOutputField nmc_fields_settings_names[] = { SETTING_FIELD (NM_SETTING_TUN_SETTING_NAME, nmc_fields_setting_tun + 1), /* 25 */ SETTING_FIELD (NM_SETTING_IP_TUNNEL_SETTING_NAME, nmc_fields_setting_ip_tunnel + 1), /* 26 */ SETTING_FIELD (NM_SETTING_MACVLAN_SETTING_NAME, nmc_fields_setting_macvlan + 1), /* 27 */ + SETTING_FIELD (NM_SETTING_VXLAN_SETTING_NAME, nmc_fields_setting_vxlan + 1), /* 28 */ {NULL, NULL, 0, NULL, NULL, FALSE, FALSE, 0} }; #define NMC_FIELDS_SETTINGS_NAMES_ALL_X NM_SETTING_CONNECTION_SETTING_NAME","\ @@ -179,7 +181,8 @@ static NmcOutputField nmc_fields_settings_names[] = { NM_SETTING_DCB_SETTING_NAME"," \ NM_SETTING_TUN_SETTING_NAME"," \ NM_SETTING_IP_TUNNEL_SETTING_NAME"," \ - NM_SETTING_MACVLAN_SETTING_NAME + NM_SETTING_MACVLAN_SETTING_NAME"," \ + NM_SETTING_VXLAN_SETTING_NAME #define NMC_FIELDS_SETTINGS_NAMES_ALL NMC_FIELDS_SETTINGS_NAMES_ALL_X /* Active connection data */ @@ -429,6 +432,13 @@ usage_connection_add (void) " macvlan: dev \n" " mode vepa|bridge|private|passthru|source\n" " [tap yes|no]\n\n" + " vxlan: id \n" + " remote \n" + " [dev ]\n" + " [local ]\n" + " [source-port-min <0-65535>]\n" + " [source-port-max <0-65535>]\n" + " [destination-port <0-65535>]\n\n" " SLAVE_OPTIONS:\n" " bridge: [priority <0-63>]\n" " [path-cost <1-65535>]\n" @@ -2826,6 +2836,14 @@ static const NameItem nmc_macvlan_settings [] = { { NULL, NULL, NULL, FALSE } }; +static const NameItem nmc_vxlan_settings [] = { + { NM_SETTING_CONNECTION_SETTING_NAME, NULL, NULL, TRUE }, + { NM_SETTING_VXLAN_SETTING_NAME, NULL, NULL, TRUE }, + { NM_SETTING_IP4_CONFIG_SETTING_NAME, NULL, NULL, FALSE }, + { NM_SETTING_IP6_CONFIG_SETTING_NAME, NULL, NULL, FALSE }, + { NULL, NULL, NULL, FALSE } +}; + /* Available connection types */ static const NameItem nmc_valid_connection_types[] = { { NM_SETTING_GENERIC_SETTING_NAME, NULL, nmc_generic_settings }, @@ -2850,6 +2868,7 @@ static const NameItem nmc_valid_connection_types[] = { { NM_SETTING_TUN_SETTING_NAME, NULL, nmc_tun_settings }, { NM_SETTING_IP_TUNNEL_SETTING_NAME, NULL, nmc_ip_tunnel_settings }, { NM_SETTING_MACVLAN_SETTING_NAME, NULL, nmc_macvlan_settings }, + { NM_SETTING_VXLAN_SETTING_NAME, NULL, nmc_vxlan_settings }, { NULL, NULL, NULL } }; @@ -4222,7 +4241,6 @@ do_questionnaire_adsl (gboolean echo, char **password, char **encapsulation) } } - static void do_questionnaire_macvlan (char **tap) { @@ -4249,6 +4267,85 @@ do_questionnaire_macvlan (char **tap) } } +static void +do_questionnaire_vxlan (char **parent, char **local, char **src_port_min, + char **src_port_max, char **dst_port) +{ + unsigned long tmp; + gboolean once_more; + + /* Ask for optional 'vxlan' arguments. */ + if (!want_provide_opt_args (_("VXLAN"), 4)) + return; + + if (!*parent) { + do { + *parent = nmc_readline (_("Parent device [none]: ")); + once_more = *parent + && !nm_utils_is_uuid (*parent) + && !nm_utils_iface_valid_name (*parent); + if (once_more) { + g_print (_("Error: 'dev': '%s' is neither UUID nor interface name.\n"), + *parent); + g_free (*parent); + } + } while (once_more); + } + + if (!*local) { + do { + *local = nmc_readline (_("Local address [none]: ")); + once_more = *local + && !nm_utils_ipaddr_valid (AF_INET, *local) + && !nm_utils_ipaddr_valid (AF_INET6, *local); + if (once_more) { + g_print (_("Error: 'local': '%s' is not a valid IP address.\n"), + *local); + g_free (*local); + } + } while (once_more); + } + + if (!*src_port_min) { + do { + *src_port_min = nmc_readline (_("Minimum source port [0]: ")); + *src_port_min = *src_port_min ? *src_port_min : g_strdup ("0"); + once_more = !nmc_string_to_uint (*src_port_min, TRUE, 0, 65535, &tmp); + if (once_more) { + g_print (_("Error: 'source-port-min': '%s' is not a valid number <0-65535>.\n"), + *src_port_min); + g_free (*src_port_min); + } + } while (once_more); + } + + if (!*src_port_max) { + do { + *src_port_max = nmc_readline (_("Maximum source port [0]: ")); + *src_port_max = *src_port_max ? *src_port_max : g_strdup ("0"); + once_more = !nmc_string_to_uint (*src_port_max, TRUE, 0, 65535, &tmp); + if (once_more) { + g_print (_("Error: 'source-port-max': '%s' is not a valid number <0-65535>.\n"), + *src_port_max); + g_free (*src_port_max); + } + } while (once_more); + } + + if (!*dst_port) { + do { + *dst_port = nmc_readline (_("Destination port [8472]: ")); + *dst_port = *dst_port ? *dst_port : g_strdup ("8472"); + once_more = !nmc_string_to_uint (*dst_port, TRUE, 0, 65535, &tmp); + if (once_more) { + g_print (_("Error: 'destination-port': '%s' is not a valid number <0-65535>.\n"), + *dst_port); + g_free (*dst_port); + } + } while (once_more); + } +} + static gboolean split_address (char* str, char **ip, char **rest) { @@ -4720,6 +4817,7 @@ complete_connection_by_type (NMConnection *connection, NMSettingTun *s_tun; NMSettingIPTunnel *s_ip_tunnel; NMSettingMacvlan *s_macvlan; + NMSettingVxlan *s_vxlan; const char *slave_type; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -6119,6 +6217,144 @@ cleanup_tun: cleanup_tunnel: g_free (remote_ask); g_free (mode_ask); + } else if (!strcmp (con_type, NM_SETTING_VXLAN_SETTING_NAME)) { + /* Build up the settings required for 'vxlan' */ + gboolean success = FALSE; + char *id_ask = NULL; + const char *id = NULL; + char *remote_ask = NULL; + const char *remote = NULL; + const char *parent_c = NULL, *local_c = NULL; + const char *src_port_min_c = NULL, *src_port_max_c = NULL; + const char *dst_port_c = NULL; + char *parent = NULL, *local = NULL; + char *src_port_min = NULL, *src_port_max = NULL, *dst_port = NULL; + unsigned long int vni; + unsigned long sport_min = G_MAXULONG, sport_max = G_MAXULONG; + unsigned long dport = G_MAXULONG; + nmc_arg_t exp_args[] = { {"id", TRUE, &id, !ask}, + {"remote", TRUE, &remote, !ask}, + {"dev", TRUE, &parent_c, FALSE}, + {"local", TRUE, &local_c, FALSE}, + {"source-port-min", TRUE, &src_port_min_c, FALSE}, + {"source-port-max", TRUE, &src_port_max_c, FALSE}, + {"destination-port", TRUE, &dst_port_c, FALSE}, + {NULL} }; + + if (!nmc_parse_args (exp_args, FALSE, &argc, &argv, error)) + return FALSE; + + if (!id && ask) + id = id_ask = nmc_readline (_("VXLAN ID: ")); + if (!id) { + g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'id' is required.")); + goto cleanup_vxlan; + } + + if (!remote && ask) + remote = remote_ask = nmc_readline (_("Remote: ")); + if (!remote) { + g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'remote' is required.")); + goto cleanup_vxlan; + } + + if (!nmc_string_to_uint (id, TRUE, 0, (1UL << 24) - 1, &vni)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'id': '%s' is not valid; use <0-16777215>."), id); + goto cleanup_vxlan; + } + + parent = g_strdup (parent_c); + local = g_strdup (local_c); + src_port_min = g_strdup (src_port_min_c); + src_port_max = g_strdup (src_port_max_c); + dst_port = g_strdup (dst_port_c); + + if (ask) + do_questionnaire_vxlan (&parent, &local, &src_port_min, &src_port_max, &dst_port); + + if (parent) { + if ( !nm_utils_is_uuid (parent) + && !nm_utils_iface_valid_name (parent)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'dev': '%s' is neither UUID nor interface name."), + parent); + goto cleanup_vxlan; + } + } + + if ( !nm_utils_ipaddr_valid (AF_INET, remote) + && !nm_utils_ipaddr_valid (AF_INET6, remote)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'remote': '%s' is not a valid IP address"), + remote); + goto cleanup_vxlan; + } + + if (local) { + if ( !nm_utils_ipaddr_valid (AF_INET, local) + && !nm_utils_ipaddr_valid (AF_INET6, local)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'local': '%s' is not a valid IP address"), + local); + goto cleanup_vxlan; + } + } + + if (src_port_min) { + if (!nmc_string_to_uint (src_port_min, TRUE, 0, 65535, &sport_min)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'source-port-min': %s is not valid; use <0-65535>."), + src_port_min); + goto cleanup_vxlan; + } + } + + if (src_port_max) { + if (!nmc_string_to_uint (src_port_max, TRUE, 0, 65535, &sport_max)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'source-port-max': %s is not valid; use <0-65535>."), + src_port_max); + goto cleanup_vxlan; + } + } + + if (dst_port) { + if (!nmc_string_to_uint (dst_port, TRUE, 0, 65535, &dport)) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("Error: 'destination-port': %s is not valid; use <0-65535>."), + dst_port); + goto cleanup_vxlan; + } + } + + /* Add 'vxlan' setting */ + s_vxlan = (NMSettingVxlan *) nm_setting_vxlan_new (); + nm_connection_add_setting (connection, NM_SETTING (s_vxlan)); + + g_object_set (s_vxlan, NM_SETTING_VXLAN_ID, (guint) vni, NULL); + g_object_set (s_vxlan, NM_SETTING_VXLAN_REMOTE, remote, NULL); + g_object_set (s_vxlan, NM_SETTING_VXLAN_LOCAL, local, NULL); + g_object_set (s_vxlan, NM_SETTING_VXLAN_PARENT, parent, NULL); + + if (sport_min != G_MAXULONG) + g_object_set (s_vxlan, NM_SETTING_VXLAN_SOURCE_PORT_MIN, sport_min, NULL); + if (sport_max != G_MAXULONG) + g_object_set (s_vxlan, NM_SETTING_VXLAN_SOURCE_PORT_MAX, sport_max, NULL); + if (dport != G_MAXULONG) + g_object_set (s_vxlan, NM_SETTING_VXLAN_DESTINATION_PORT, dport, NULL); + + success = TRUE; + +cleanup_vxlan: + g_free (id_ask); + g_free (remote_ask); + g_free (parent); + g_free (local); + g_free (src_port_min); + g_free (src_port_max); if (!success) return FALSE; diff --git a/clients/cli/nmcli-completion b/clients/cli/nmcli-completion index aefd902a23..c83be993d2 100644 --- a/clients/cli/nmcli-completion +++ b/clients/cli/nmcli-completion @@ -412,7 +412,7 @@ _nmcli_compl_ARGS() # user friendly. Only complete them, if the current word already starts with an "8". _nmcli_list "802-3-ethernet 802-11-wireless 802-11-olpc-mesh" else - _nmcli_list "ethernet wifi wimax gsm cdma infiniband bluetooth vpn olpc-mesh vlan bond bridge team pppoe adsl tun ip-tunnel macvlan" + _nmcli_list "ethernet wifi wimax gsm cdma infiniband bluetooth vpn olpc-mesh vlan bond bridge team pppoe adsl tun ip-tunnel macvlan vxlan" fi return 0 fi diff --git a/clients/cli/settings.c b/clients/cli/settings.c index 05e5580165..f122c38ea3 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -764,6 +764,46 @@ NmcOutputField nmc_fields_setting_macvlan[] = { NM_SETTING_MACVLAN_TAP #define NMC_FIELDS_SETTING_MACVLAN_COMMON NMC_FIELDS_SETTING_MACVLAN_ALL +/* Available fields for NM_SETTING_VXLAN_SETTING_NAME */ +NmcOutputField nmc_fields_setting_vxlan[] = { + SETTING_FIELD ("name"), /* 0 */ + SETTING_FIELD (NM_SETTING_VXLAN_PARENT), /* 1 */ + SETTING_FIELD (NM_SETTING_VXLAN_ID), /* 2 */ + SETTING_FIELD (NM_SETTING_VXLAN_LOCAL), /* 3 */ + SETTING_FIELD (NM_SETTING_VXLAN_REMOTE), /* 4 */ + SETTING_FIELD (NM_SETTING_VXLAN_SOURCE_PORT_MIN), /* 5 */ + SETTING_FIELD (NM_SETTING_VXLAN_SOURCE_PORT_MAX), /* 6 */ + SETTING_FIELD (NM_SETTING_VXLAN_DESTINATION_PORT), /* 7 */ + SETTING_FIELD (NM_SETTING_VXLAN_TOS), /* 8 */ + SETTING_FIELD (NM_SETTING_VXLAN_TTL), /* 9 */ + SETTING_FIELD (NM_SETTING_VXLAN_AGEING), /* 10 */ + SETTING_FIELD (NM_SETTING_VXLAN_LIMIT), /* 11 */ + SETTING_FIELD (NM_SETTING_VXLAN_LEARNING), /* 12 */ + SETTING_FIELD (NM_SETTING_VXLAN_PROXY), /* 13 */ + SETTING_FIELD (NM_SETTING_VXLAN_RSC), /* 14 */ + SETTING_FIELD (NM_SETTING_VXLAN_L2_MISS), /* 15 */ + SETTING_FIELD (NM_SETTING_VXLAN_L3_MISS), /* 16 */ + {NULL, NULL, 0, NULL, FALSE, FALSE, 0} +}; +#define NMC_FIELDS_SETTING_VXLAN_ALL "name"","\ + NM_SETTING_VXLAN_PARENT","\ + NM_SETTING_VXLAN_ID","\ + NM_SETTING_VXLAN_LOCAL","\ + NM_SETTING_VXLAN_REMOTE","\ + NM_SETTING_VXLAN_SOURCE_PORT_MIN","\ + NM_SETTING_VXLAN_SOURCE_PORT_MAX","\ + NM_SETTING_VXLAN_DESTINATION_PORT","\ + NM_SETTING_VXLAN_TOS","\ + NM_SETTING_VXLAN_TTL","\ + NM_SETTING_VXLAN_AGEING","\ + NM_SETTING_VXLAN_LIMIT","\ + NM_SETTING_VXLAN_LEARNING","\ + NM_SETTING_VXLAN_PROXY","\ + NM_SETTING_VXLAN_RSC","\ + NM_SETTING_VXLAN_L2_MISS","\ + NM_SETTING_VXLAN_L3_MISS +#define NMC_FIELDS_SETTING_VXLAN_COMMON NMC_FIELDS_SETTING_VXLAN_ALL + /*----------------------------------------------------------------------------*/ static char * wep_key_type_to_string (NMWepKeyType type) @@ -1937,6 +1977,24 @@ nmc_property_macvlan_set_mode (NMSetting *setting, const char *prop, return TRUE; } +/* --- NM_SETTING_VXLAN_SETTING_NAME property get functions --- */ +DEFINE_GETTER (nmc_property_vxlan_get_parent, NM_SETTING_VXLAN_PARENT) +DEFINE_GETTER (nmc_property_vxlan_get_id, NM_SETTING_VXLAN_ID) +DEFINE_GETTER (nmc_property_vxlan_get_local, NM_SETTING_VXLAN_LOCAL) +DEFINE_GETTER (nmc_property_vxlan_get_remote, NM_SETTING_VXLAN_REMOTE) +DEFINE_GETTER (nmc_property_vxlan_get_source_port_min, NM_SETTING_VXLAN_SOURCE_PORT_MIN) +DEFINE_GETTER (nmc_property_vxlan_get_source_port_max, NM_SETTING_VXLAN_SOURCE_PORT_MAX) +DEFINE_GETTER (nmc_property_vxlan_get_destination_port, NM_SETTING_VXLAN_DESTINATION_PORT) +DEFINE_GETTER (nmc_property_vxlan_get_tos, NM_SETTING_VXLAN_TOS) +DEFINE_GETTER (nmc_property_vxlan_get_ttl, NM_SETTING_VXLAN_TTL) +DEFINE_GETTER (nmc_property_vxlan_get_ageing, NM_SETTING_VXLAN_AGEING) +DEFINE_GETTER (nmc_property_vxlan_get_limit, NM_SETTING_VXLAN_LIMIT) +DEFINE_GETTER (nmc_property_vxlan_get_learning, NM_SETTING_VXLAN_LEARNING) +DEFINE_GETTER (nmc_property_vxlan_get_proxy, NM_SETTING_VXLAN_PROXY) +DEFINE_GETTER (nmc_property_vxlan_get_rsc, NM_SETTING_VXLAN_RSC) +DEFINE_GETTER (nmc_property_vxlan_get_l2_miss, NM_SETTING_VXLAN_L2_MISS) +DEFINE_GETTER (nmc_property_vxlan_get_l3_miss, NM_SETTING_VXLAN_L3_MISS) + /*----------------------------------------------------------------------------*/ static void @@ -7332,6 +7390,120 @@ nmc_properties_init (void) NULL, NULL, NULL); + + /* Add editable properties for NM_SETTING_VXLAN_SETTING_NAME */ + nmc_add_prop_funcs (GLUE (VXLAN, PARENT), + nmc_property_vxlan_get_parent, + nmc_property_set_string, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, ID), + nmc_property_vxlan_get_id, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, LOCAL), + nmc_property_vxlan_get_local, + nmc_property_set_string, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, REMOTE), + nmc_property_vxlan_get_remote, + nmc_property_set_string, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, SOURCE_PORT_MIN), + nmc_property_vxlan_get_source_port_min, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, SOURCE_PORT_MAX), + nmc_property_vxlan_get_source_port_max, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, DESTINATION_PORT), + nmc_property_vxlan_get_destination_port, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, TOS), + nmc_property_vxlan_get_tos, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, TTL), + nmc_property_vxlan_get_ttl, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, AGEING), + nmc_property_vxlan_get_ageing, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, LIMIT), + nmc_property_vxlan_get_limit, + nmc_property_set_uint, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, LEARNING), + nmc_property_vxlan_get_learning, + nmc_property_set_bool, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, PROXY), + nmc_property_vxlan_get_proxy, + nmc_property_set_bool, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, RSC), + nmc_property_vxlan_get_rsc, + nmc_property_set_bool, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, L2_MISS), + nmc_property_vxlan_get_l2_miss, + nmc_property_set_bool, + NULL, + NULL, + NULL, + NULL); + nmc_add_prop_funcs (GLUE (VXLAN, L3_MISS), + nmc_property_vxlan_get_l3_miss, + nmc_property_set_bool, + NULL, + NULL, + NULL, + NULL); } void @@ -8577,6 +8749,47 @@ setting_macvlan_details (NMSetting *setting, NmCli *nmc, const char *one_prop, return TRUE; } + static gboolean +setting_vxlan_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gboolean secrets) +{ + NMSettingVxlan *s_vxlan = NM_SETTING_VXLAN (setting); + NmcOutputField *tmpl, *arr; + size_t tmpl_len; + + g_return_val_if_fail (NM_IS_SETTING_VXLAN (s_vxlan), FALSE); + + tmpl = nmc_fields_setting_vxlan; + tmpl_len = sizeof (nmc_fields_setting_vxlan); + nmc->print_fields.indices = parse_output_fields (one_prop ? one_prop : NMC_FIELDS_SETTING_VXLAN_ALL, + tmpl, FALSE, NULL, NULL); + arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES); + g_ptr_array_add (nmc->output_data, arr); + + arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX); + set_val_str (arr, 0, g_strdup (nm_setting_get_name (setting))); + set_val_str (arr, 1, nmc_property_vxlan_get_parent (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 2, nmc_property_vxlan_get_id (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 3, nmc_property_vxlan_get_local (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 4, nmc_property_vxlan_get_remote (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 5, nmc_property_vxlan_get_source_port_min (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 6, nmc_property_vxlan_get_source_port_max (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 7, nmc_property_vxlan_get_destination_port (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 8, nmc_property_vxlan_get_tos (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 9, nmc_property_vxlan_get_ttl (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 10, nmc_property_vxlan_get_ageing (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 11, nmc_property_vxlan_get_limit (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 12, nmc_property_vxlan_get_learning (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 13, nmc_property_vxlan_get_proxy (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 14, nmc_property_vxlan_get_rsc (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 15, nmc_property_vxlan_get_l2_miss (setting, NMC_PROPERTY_GET_PRETTY)); + set_val_str (arr, 16, nmc_property_vxlan_get_l3_miss (setting, NMC_PROPERTY_GET_PRETTY)); + g_ptr_array_add (nmc->output_data, arr); + + print_data (nmc); /* Print all data */ + + return TRUE; +} + typedef struct { const char *sname; gboolean (*func) (NMSetting *setting, NmCli *nmc, const char *one_prop, gboolean secrets); @@ -8611,6 +8824,7 @@ static const SettingDetails detail_printers[] = { { NM_SETTING_TUN_SETTING_NAME, setting_tun_details }, { NM_SETTING_IP_TUNNEL_SETTING_NAME, setting_ip_tunnel_details }, { NM_SETTING_MACVLAN_SETTING_NAME, setting_macvlan_details }, + { NM_SETTING_VXLAN_SETTING_NAME, setting_vxlan_details }, { NULL }, }; diff --git a/introspection/nm-device-vxlan.xml b/introspection/nm-device-vxlan.xml index 053eea4d2d..4dd254a223 100644 --- a/introspection/nm-device-vxlan.xml +++ b/introspection/nm-device-vxlan.xml @@ -10,6 +10,12 @@ + + + Hardware address of the device. + + + The VXLAN Network Identifier (VNI). diff --git a/libnm-core/Makefile.libnm-core b/libnm-core/Makefile.libnm-core index 8a81f00f10..df219295c4 100644 --- a/libnm-core/Makefile.libnm-core +++ b/libnm-core/Makefile.libnm-core @@ -38,6 +38,7 @@ libnm_core_headers = \ $(core)/nm-setting-tun.h \ $(core)/nm-setting-vlan.h \ $(core)/nm-setting-vpn.h \ + $(core)/nm-setting-vxlan.h \ $(core)/nm-setting-wimax.h \ $(core)/nm-setting-wired.h \ $(core)/nm-setting-wireless-security.h \ @@ -97,6 +98,7 @@ libnm_core_sources = \ $(core)/nm-setting-tun.c \ $(core)/nm-setting-vlan.c \ $(core)/nm-setting-vpn.c \ + $(core)/nm-setting-vxlan.c \ $(core)/nm-setting-wimax.c \ $(core)/nm-setting-wired.c \ $(core)/nm-setting-wireless-security.c \ diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 73ff9e5558..5a491b4068 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -1597,7 +1597,8 @@ nm_connection_is_virtual (NMConnection *connection) || !strcmp (type, NM_SETTING_VLAN_SETTING_NAME) || !strcmp (type, NM_SETTING_TUN_SETTING_NAME) || !strcmp (type, NM_SETTING_IP_TUNNEL_SETTING_NAME) - || !strcmp (type, NM_SETTING_MACVLAN_SETTING_NAME)) + || !strcmp (type, NM_SETTING_MACVLAN_SETTING_NAME) + || !strcmp (type, NM_SETTING_VXLAN_SETTING_NAME)) return TRUE; if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) { @@ -2022,6 +2023,24 @@ nm_connection_get_setting_vpn (NMConnection *connection) return (NMSettingVpn *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN); } +/** + * nm_connection_get_setting_vxlan: + * @connection: the #NMConnection + * + * A shortcut to return any #NMSettingVxlan the connection might contain. + * + * Returns: (transfer none): an #NMSettingVxlan if the connection contains one, otherwise %NULL + * + * Since: 1.2 + **/ +NMSettingVxlan * +nm_connection_get_setting_vxlan (NMConnection *connection) +{ + g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); + + return (NMSettingVxlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VXLAN); +} + /** * nm_connection_get_setting_wimax: * @connection: the #NMConnection diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h index 855fbc4c5b..21e30422c8 100644 --- a/libnm-core/nm-connection.h +++ b/libnm-core/nm-connection.h @@ -220,6 +220,8 @@ NMSettingWired * nm_connection_get_setting_wired (NMConnec NMSettingWireless * nm_connection_get_setting_wireless (NMConnection *connection); NMSettingWirelessSecurity *nm_connection_get_setting_wireless_security (NMConnection *connection); NMSettingVlan * nm_connection_get_setting_vlan (NMConnection *connection); +NM_AVAILABLE_IN_1_2 +NMSettingVxlan * nm_connection_get_setting_vxlan (NMConnection *connection); G_END_DECLS diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index f2c6c6c07e..3e1236b975 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -62,6 +62,7 @@ #include "nm-setting-tun.h" #include "nm-setting-vlan.h" #include "nm-setting-vpn.h" +#include "nm-setting-vxlan.h" #include "nm-setting-wimax.h" #include "nm-setting-wired.h" #include "nm-setting-wireless-security.h" diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h index 68a1ebc6e6..cd19923b7e 100644 --- a/libnm-core/nm-core-types.h +++ b/libnm-core/nm-core-types.h @@ -55,6 +55,7 @@ typedef struct _NMSettingTeamPort NMSettingTeamPort; typedef struct _NMSettingTun NMSettingTun; typedef struct _NMSettingVlan NMSettingVlan; typedef struct _NMSettingVpn NMSettingVpn; +typedef struct _NMSettingVxlan NMSettingVxlan; typedef struct _NMSettingWimax NMSettingWimax; typedef struct _NMSettingWired NMSettingWired; typedef struct _NMSettingWireless NMSettingWireless; diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index df10e9d80c..b32aabc2b5 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -151,6 +151,7 @@ typedef enum { * @NM_DEVICE_TYPE_TUN: a TUN or TAP interface * @NM_DEVICE_TYPE_IP_TUNNEL: a IP tunnel interface * @NM_DEVICE_TYPE_MACVLAN: a MACVLAN interface + * @NM_DEVICE_TYPE_VXLAN: a VXLAN interface * * #NMDeviceType values indicate the type of hardware represented by * an #NMDevice. @@ -177,6 +178,7 @@ typedef enum { NM_DEVICE_TYPE_TUN = 16, NM_DEVICE_TYPE_IP_TUNNEL = 17, NM_DEVICE_TYPE_MACVLAN = 18, + NM_DEVICE_TYPE_VXLAN = 19, } NMDeviceType; /** diff --git a/libnm-core/nm-setting-vxlan.c b/libnm-core/nm-setting-vxlan.c new file mode 100644 index 0000000000..814623b735 --- /dev/null +++ b/libnm-core/nm-setting-vxlan.c @@ -0,0 +1,843 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#include "config.h" + +#include +#include + +#include "nm-setting-vxlan.h" +#include "nm-utils.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-vxlan + * @short_description: Describes connection properties for VXLAN interfaces + * + * The #NMSettingVxlan object is a #NMSetting subclass that describes properties + * necessary for connection to VXLAN interfaces. + **/ + +G_DEFINE_TYPE_WITH_CODE (NMSettingVxlan, nm_setting_vxlan, NM_TYPE_SETTING, + _nm_register_setting (VXLAN, 1)) +NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VXLAN) + +#define NM_SETTING_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VXLAN, NMSettingVxlanPrivate)) + +typedef struct { + char *parent; + guint id; + char *local; + char *remote; + guint source_port_min; + guint source_port_max; + guint destination_port; + guint tos; + guint ttl; + guint ageing; + guint limit; + gboolean learning; + gboolean proxy; + gboolean rsc; + gboolean l2_miss; + gboolean l3_miss; +} NMSettingVxlanPrivate; + +enum { + PROP_0, + PROP_PARENT, + PROP_ID, + PROP_LOCAL, + PROP_REMOTE, + PROP_SOURCE_PORT_MIN, + PROP_SOURCE_PORT_MAX, + PROP_DESTINATION_PORT, + PROP_TOS, + PROP_TTL, + PROP_AGEING, + PROP_LIMIT, + PROP_LEARNING, + PROP_PROXY, + PROP_RSC, + PROP_L2_MISS, + PROP_L3_MISS, + + LAST_PROP +}; + +#define DST_PORT_DEFAULT 8472 + +/** + * nm_setting_vxlan_new: + * + * Creates a new #NMSettingVxlan object with default values. + * + * Returns: (transfer full): the new empty #NMSettingVxlan object + * + * Since: 1.2 + **/ +NMSetting * +nm_setting_vxlan_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_VXLAN, NULL); +} + +/** + * nm_setting_vxlan_get_parent: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:parent property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_vxlan_get_parent (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), NULL); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->parent; +} + +/** + * nm_setting_vxlan_get_id: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:id property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_id (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->id; +} + +/** + * nm_setting_vxlan_get_local: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:local property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_vxlan_get_local (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), NULL); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->local; +} + +/** + * nm_setting_vxlan_get_remote: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:remote property of the setting + * + * Since: 1.2 + **/ +const char * +nm_setting_vxlan_get_remote (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), NULL); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->remote; +} + +/** + * nm_setting_vxlan_get_source_port_min: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:source-port-min property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_source_port_min (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->source_port_min; +} + +/** + * nm_setting_vxlan_get_source_port_max: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:source-port-max property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_source_port_max (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->source_port_max; +} + +/** + * nm_setting_vxlan_get_destination_port: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:destination-port property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_destination_port (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), DST_PORT_DEFAULT); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->destination_port; +} + +/** + * nm_setting_vxlan_get_proxy: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:proxy property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_proxy (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->proxy; +} + +/** + * nm_setting_vxlan_get_ageing: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:ageing property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_ageing (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->ageing; +} + +/** + * nm_setting_vxlan_get_limit: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:limit property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_limit (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->limit; +} + +/** + * nm_setting_vxlan_get_tos: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:tos property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_tos (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->tos; +} + +/** + * nm_setting_vxlan_get_ttl: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:ttl property of the setting + * + * Since: 1.2 + **/ +guint +nm_setting_vxlan_get_ttl (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), 0); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->ttl; +} + +/** + * nm_setting_vxlan_get_learning: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:learning property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_learning (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->learning; +} + +/** + * nm_setting_vxlan_get_rsc: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:rsc property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_rsc (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->rsc; +} + +/** + * nm_setting_vxlan_get_l2_miss: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:l2_miss property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_l2_miss (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->l2_miss; +} + +/** + * nm_setting_vxlan_get_l3_miss: + * @setting: the #NMSettingVxlan + * + * Returns: the #NMSettingVxlan:l3_miss property of the setting + * + * Since: 1.2 + **/ +gboolean +nm_setting_vxlan_get_l3_miss (NMSettingVxlan *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_VXLAN (setting), FALSE); + return NM_SETTING_VXLAN_GET_PRIVATE (setting)->l3_miss; +} + +/*********************************************************************/ + +static void +nm_setting_vxlan_init (NMSettingVxlan *setting) +{ +} + +static gboolean +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE (setting); + int family = AF_UNSPEC; + + if (!priv->remote) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_VXLAN_SETTING_NAME, + NM_SETTING_VXLAN_REMOTE); + return FALSE; + } + + if (nm_utils_ipaddr_valid (AF_INET, priv->remote)) + family = AF_INET; + else if (nm_utils_ipaddr_valid (AF_INET6, priv->remote)) + family = AF_INET6; + else { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IP address"), + priv->remote); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_VXLAN_SETTING_NAME, + NM_SETTING_VXLAN_REMOTE); + return FALSE; + } + + if (priv->local) { + if (!nm_utils_ipaddr_valid (family, priv->local)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is not a valid IP%c address"), + priv->local, family == AF_INET ? '4' : '6'); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_VXLAN_SETTING_NAME, + NM_SETTING_VXLAN_LOCAL); + return FALSE; + } + } + + if ( priv->parent + && !nm_utils_iface_valid_name (priv->parent) + && !nm_utils_is_uuid (priv->parent)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("'%s' is neither an UUID nor an interface name"), + priv->parent); + g_prefix_error (error, "%s.%s: ", NM_SETTING_VXLAN_SETTING_NAME, + NM_SETTING_VXLAN_PARENT); + return FALSE; + } + + if ( (priv->source_port_min || priv->source_port_max) + && (priv->source_port_min > priv->source_port_max)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%d is greater than local port max %d"), + priv->source_port_min, + priv->source_port_max); + g_prefix_error (error, "%s.%s: ", + NM_SETTING_VXLAN_SETTING_NAME, + NM_SETTING_VXLAN_SOURCE_PORT_MIN); + return FALSE; + } + + return TRUE; +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingVxlan *setting = NM_SETTING_VXLAN (object); + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_PARENT: + g_free (priv->parent); + priv->parent = g_value_dup_string (value); + break; + case PROP_ID: + priv->id = g_value_get_uint (value); + break; + case PROP_LOCAL: + g_free (priv->local); + priv->local = g_value_dup_string (value); + break; + case PROP_REMOTE: + g_free (priv->remote); + priv->remote = g_value_dup_string (value); + break; + case PROP_SOURCE_PORT_MIN: + priv->source_port_min = g_value_get_uint (value); + break; + case PROP_SOURCE_PORT_MAX: + priv->source_port_max = g_value_get_uint (value); + break; + case PROP_DESTINATION_PORT: + priv->destination_port = g_value_get_uint (value); + break; + case PROP_TOS: + priv->tos = g_value_get_uint (value); + break; + case PROP_AGEING: + priv->ageing = g_value_get_uint (value); + break; + case PROP_LIMIT: + priv->limit = g_value_get_uint (value); + break; + case PROP_PROXY: + priv->proxy = g_value_get_boolean (value); + break; + case PROP_TTL: + priv->ttl = g_value_get_uint (value); + break; + case PROP_LEARNING: + priv->learning = g_value_get_boolean (value); + break; + case PROP_RSC: + priv->rsc = g_value_get_boolean (value); + break; + case PROP_L2_MISS: + priv->l2_miss = g_value_get_boolean (value); + break; + case PROP_L3_MISS: + priv->l3_miss = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingVxlan *setting = NM_SETTING_VXLAN (object); + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE (setting); + + switch (prop_id) { + case PROP_PARENT: + g_value_set_string (value, priv->parent); + break; + case PROP_ID: + g_value_set_uint (value, priv->id); + break; + case PROP_LOCAL: + g_value_set_string (value, priv->local); + break; + case PROP_REMOTE: + g_value_set_string (value, priv->remote); + break; + case PROP_SOURCE_PORT_MIN: + g_value_set_uint (value, priv->source_port_min); + break; + case PROP_SOURCE_PORT_MAX: + g_value_set_uint (value, priv->source_port_max); + break; + case PROP_DESTINATION_PORT: + g_value_set_uint (value, priv->destination_port); + break; + case PROP_TOS: + g_value_set_uint (value, priv->tos); + break; + case PROP_AGEING: + g_value_set_uint (value, priv->ageing); + break; + case PROP_LIMIT: + g_value_set_uint (value, priv->limit); + break; + case PROP_PROXY: + g_value_set_boolean (value, priv->proxy); + break; + case PROP_TTL: + g_value_set_uint (value, priv->ttl); + break; + case PROP_LEARNING: + g_value_set_boolean (value, priv->learning); + break; + case PROP_RSC: + g_value_set_boolean (value, priv->rsc); + break; + case PROP_L2_MISS: + g_value_set_boolean (value, priv->l2_miss); + break; + case PROP_L3_MISS: + g_value_set_boolean (value, priv->l3_miss); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +finalize (GObject *object) +{ + NMSettingVxlan *setting = NM_SETTING_VXLAN (object); + NMSettingVxlanPrivate *priv = NM_SETTING_VXLAN_GET_PRIVATE (setting); + + g_free (priv->parent); + g_free (priv->local); + g_free (priv->remote); + + G_OBJECT_CLASS (nm_setting_vxlan_parent_class)->finalize (object); +} + +static void +nm_setting_vxlan_class_init (NMSettingVxlanClass *setting_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_class); + NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class); + + g_type_class_add_private (setting_class, sizeof (NMSettingVxlanPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + parent_class->verify = verify; + + /* Properties */ + + /** + * NMSettingVxlan:parent: + * + * If given, specifies the parent interface name or parent connection UUID. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_string (NM_SETTING_VXLAN_PARENT, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + /** + * NMSettingVxlan:id: + * + * Specifies the VXLAN Network Identifer (or VXLAN Segment Identifier) to + * use. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_ID, + g_param_spec_uint (NM_SETTING_VXLAN_ID, "", "", + 0, (1 << 24) - 1, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:local: + * + * If given, specifies the source IP address to use in outgoing packets. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_LOCAL, + g_param_spec_string (NM_SETTING_VXLAN_LOCAL, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:remote: + * + * Specifies the unicast destination IP address to use in outgoing packets + * when the destination link layer address is not known in the VXLAN device + * forwarding database, or the multicast IP address to join. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_REMOTE, + g_param_spec_string (NM_SETTING_VXLAN_REMOTE, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:source-port-min: + * + * Specifies the minimum UDP source port to communicate to the remote VXLAN + * tunnel endpoint. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_SOURCE_PORT_MIN, + g_param_spec_uint (NM_SETTING_VXLAN_SOURCE_PORT_MIN, "", "", + 0, G_MAXUINT16, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:source-port-max: + * + * Specifies the maximum UDP source port to communicate to the remote VXLAN + * tunnel endpoint. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_SOURCE_PORT_MAX, + g_param_spec_uint (NM_SETTING_VXLAN_SOURCE_PORT_MAX, "", "", + 0, G_MAXUINT16, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:destination-port: + * + * Specifies the UDP destination port to communicate to the remote VXLAN + * tunnel endpoint. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_DESTINATION_PORT, + g_param_spec_uint (NM_SETTING_VXLAN_DESTINATION_PORT, "", "", + 0, G_MAXUINT16, DST_PORT_DEFAULT, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:ageing: + * + * Specifies the lifetime in seconds of FDB entries learnt by the kernel. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_AGEING, + g_param_spec_uint (NM_SETTING_VXLAN_AGEING, "", "", + 0, G_MAXINT32, 300, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:limit: + * + * Specifies the maximum number of FDB entries. A value of zero means that + * the kernel will store unlimited entries. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_AGEING, + g_param_spec_uint (NM_SETTING_VXLAN_LIMIT, "", "", + 0, G_MAXINT32, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:tos: + * + * Specifies the TOS value to use in outgoing packets. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_TOS, + g_param_spec_uint (NM_SETTING_VXLAN_TOS, "", "", + 0, 255, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:ttl: + * + * Specifies the time-to-live value to use in outgoing packets. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_TTL, + g_param_spec_uint (NM_SETTING_VXLAN_TTL, "", "", + 0, 255, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:proxy: + * + * Specifies whether ARP proxy is turned on. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_PROXY, + g_param_spec_boolean (NM_SETTING_VXLAN_PROXY, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:learning: + * + * Specifies whether unknown source link layer addresses and IP addresses + * are entered into the VXLAN device forwarding database. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_LEARNING, + g_param_spec_boolean (NM_SETTING_VXLAN_LEARNING, "", "", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + /** + * NMSettingVxlan:rsc: + * + * Specifies whether route short circuit is turned on. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_RSC, + g_param_spec_boolean (NM_SETTING_VXLAN_RSC, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + /** + * NMSettingVxlan:l2-miss: + * + * Specifies whether netlink LL ADDR miss notifications are generated. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_L2_MISS, + g_param_spec_boolean (NM_SETTING_VXLAN_L2_MISS, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSettingVxlan:l3-miss: + * + * Specifies whether netlink IP ADDR miss notifications are generated. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_L3_MISS, + g_param_spec_boolean (NM_SETTING_VXLAN_L3_MISS, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + NM_SETTING_PARAM_INFERRABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm-core/nm-setting-vxlan.h b/libnm-core/nm-setting-vxlan.h new file mode 100644 index 0000000000..c410338eeb --- /dev/null +++ b/libnm-core/nm-setting-vxlan.h @@ -0,0 +1,109 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_VXLAN_H__ +#define __NM_SETTING_VXLAN_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only can be included directly." +#endif + +#include "nm-setting.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_VXLAN (nm_setting_vxlan_get_type ()) +#define NM_SETTING_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_VXLAN, NMSettingVxlan)) +#define NM_SETTING_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_VXLANCONFIG, NMSettingVxlanClass)) +#define NM_IS_SETTING_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_VXLAN)) +#define NM_IS_SETTING_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_VXLAN)) +#define NM_SETTING_VXLAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_VXLAN, NMSettingVxlanClass)) + +#define NM_SETTING_VXLAN_SETTING_NAME "vxlan" + +#define NM_SETTING_VXLAN_PARENT "parent" +#define NM_SETTING_VXLAN_ID "id" +#define NM_SETTING_VXLAN_LOCAL "local" +#define NM_SETTING_VXLAN_REMOTE "remote" +#define NM_SETTING_VXLAN_SOURCE_PORT_MIN "source-port-min" +#define NM_SETTING_VXLAN_SOURCE_PORT_MAX "source-port-max" +#define NM_SETTING_VXLAN_DESTINATION_PORT "destination-port" +#define NM_SETTING_VXLAN_TOS "tos" +#define NM_SETTING_VXLAN_TTL "ttl" +#define NM_SETTING_VXLAN_AGEING "ageing" +#define NM_SETTING_VXLAN_LIMIT "limit" +#define NM_SETTING_VXLAN_PROXY "proxy" +#define NM_SETTING_VXLAN_LEARNING "learning" +#define NM_SETTING_VXLAN_RSC "rsc" +#define NM_SETTING_VXLAN_L2_MISS "l2-miss" +#define NM_SETTING_VXLAN_L3_MISS "l3-miss" + +struct _NMSettingVxlan { + NMSetting parent; +}; + +typedef struct { + NMSettingClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMSettingVxlanClass; + +NM_AVAILABLE_IN_1_2 +GType nm_setting_vxlan_get_type (void); +NM_AVAILABLE_IN_1_2 +NMSetting *nm_setting_vxlan_new (void); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_vxlan_get_parent (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_id (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_vxlan_get_local (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +const char *nm_setting_vxlan_get_remote (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_source_port_min (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_source_port_max (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_destination_port (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_tos (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_ttl (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_ageing (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +guint nm_setting_vxlan_get_limit (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_proxy (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_learning (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_rsc (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_l2_miss (NMSettingVxlan *setting); +NM_AVAILABLE_IN_1_2 +gboolean nm_setting_vxlan_get_l3_miss (NMSettingVxlan *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_VXLAN_H__ */ diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c index ade17d579e..b1f8cfb203 100644 --- a/libnm-glib/nm-device.c +++ b/libnm-glib/nm-device.c @@ -327,8 +327,8 @@ _nm_device_gtype_from_dtype (NMDeviceType dtype) case NM_DEVICE_TYPE_IP_TUNNEL: return NM_TYPE_DEVICE_GENERIC; default: - g_warning ("Unknown device type %d", dtype); - return G_TYPE_INVALID; + /* Fall back to NMDeviceGeneric for unknown devices */ + return NM_TYPE_DEVICE_GENERIC; } } diff --git a/libnm/Makefile.am b/libnm/Makefile.am index d1e8d12a2e..253e109e21 100644 --- a/libnm/Makefile.am +++ b/libnm/Makefile.am @@ -45,6 +45,7 @@ libnminclude_hfiles = \ nm-device-team.h \ nm-device-tun.h \ nm-device-vlan.h \ + nm-device-vxlan.h \ nm-device-wifi.h \ nm-device-wimax.h \ nm-device.h \ @@ -99,6 +100,7 @@ libnm_la_csources = \ nm-device-team.c \ nm-device-tun.c \ nm-device-vlan.c \ + nm-device-vxlan.c \ nm-device-wifi.c \ nm-device-wimax.c \ nm-device.c \ diff --git a/libnm/NetworkManager.h b/libnm/NetworkManager.h index 51a703ed0e..35cd07aeca 100644 --- a/libnm/NetworkManager.h +++ b/libnm/NetworkManager.h @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 140c5004df..8eca4962c5 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -860,6 +860,7 @@ global: nm_access_point_get_last_seen; nm_connection_get_setting_ip_tunnel; nm_connection_get_setting_macvlan; + nm_connection_get_setting_vxlan; nm_connection_verify_secrets; nm_device_ethernet_get_s390_subchannels; nm_client_get_all_devices; @@ -894,6 +895,23 @@ global: nm_device_tun_get_no_pi; nm_device_tun_get_type; nm_device_tun_get_vnet_hdr; + nm_device_vxlan_get_ageing; + nm_device_vxlan_get_dst_port; + nm_device_vxlan_get_group; + nm_device_vxlan_get_hw_address; + nm_device_vxlan_get_id; + nm_device_vxlan_get_l2miss; + nm_device_vxlan_get_l3miss; + nm_device_vxlan_get_learning; + nm_device_vxlan_get_limit; + nm_device_vxlan_get_local; + nm_device_vxlan_get_parent; + nm_device_vxlan_get_proxy; + nm_device_vxlan_get_src_port_max; + nm_device_vxlan_get_src_port_min; + nm_device_vxlan_get_tos; + nm_device_vxlan_get_ttl; + nm_device_vxlan_get_type; nm_device_wifi_request_scan_options; nm_device_wifi_request_scan_options_async; nm_ip_tunnel_mode_get_type; @@ -958,6 +976,24 @@ global: nm_setting_macvlan_get_type; nm_setting_macvlan_mode_get_type; nm_setting_macvlan_new; + nm_setting_vxlan_get_ageing; + nm_setting_vxlan_get_destination_port; + nm_setting_vxlan_get_id; + nm_setting_vxlan_get_l2_miss; + nm_setting_vxlan_get_l3_miss; + nm_setting_vxlan_get_learning; + nm_setting_vxlan_get_limit; + nm_setting_vxlan_get_local; + nm_setting_vxlan_get_parent; + nm_setting_vxlan_get_proxy; + nm_setting_vxlan_get_remote; + nm_setting_vxlan_get_rsc; + nm_setting_vxlan_get_source_port_max; + nm_setting_vxlan_get_source_port_min; + nm_setting_vxlan_get_tos; + nm_setting_vxlan_get_ttl; + nm_setting_vxlan_get_type; + nm_setting_vxlan_new; nm_setting_wired_get_wake_on_lan; nm_setting_wired_get_wake_on_lan_password; nm_setting_wired_wake_on_lan_get_type; diff --git a/libnm/nm-device-vxlan.c b/libnm/nm-device-vxlan.c new file mode 100644 index 0000000000..4718080e4a --- /dev/null +++ b/libnm/nm-device-vxlan.c @@ -0,0 +1,815 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#include "config.h" + +#include + +#include +#include +#include + +#include "nm-default.h" +#include "nm-device-vxlan.h" +#include "nm-device-private.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMDeviceVxlan, nm_device_vxlan, NM_TYPE_DEVICE) + +#define NM_DEVICE_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanPrivate)) + +typedef struct { + NMDevice *parent; + char *hw_address; + gboolean carrier; + guint id; + char *group; + char *local; + guint src_port_min; + guint src_port_max; + guint dst_port; + guint tos; + guint ttl; + guint limit; + gboolean learning; + guint ageing; + gboolean proxy; + gboolean rsc; + gboolean l2miss; + gboolean l3miss; +} NMDeviceVxlanPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_CARRIER, + PROP_PARENT, + PROP_ID, + PROP_GROUP, + PROP_LOCAL, + PROP_TOS, + PROP_TTL, + PROP_LIMIT, + PROP_LEARNING, + PROP_AGEING, + PROP_DST_PORT, + PROP_SRC_PORT_MIN, + PROP_SRC_PORT_MAX, + PROP_PROXY, + PROP_RSC, + PROP_L2MISS, + PROP_L3MISS, + + LAST_PROP +}; + +/** + * nm_device_vxlan_get_hw_address: + * @device: a #NMDeviceVxlan + * + * Gets the hardware (MAC) address of the #NMDeviceVxlan + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + * + * Since: 1.2 + **/ +const char * +nm_device_vxlan_get_hw_address (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), NULL); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_vxlan_get_carrier: + * @device: a #NMDeviceVxlan + * + * Whether the device has carrier. + * + * Returns: %TRUE if the device has carrier. + * + * Since: 1.2 + **/ +gboolean +nm_device_vxlan_get_carrier (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), FALSE); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->carrier; +} + +/** + * nm_device_vxlan_get_parent: + * @device: a #NMDeviceVxlan + * + * Returns: (transfer none): the device's parent device + * + * Since: 1.2 + **/ +NMDevice * +nm_device_vxlan_get_parent (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), NULL); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->parent; +} + +/** + * nm_device_vxlan_get_id: + * @device: a #NMDeviceVxlan + * + * Returns: the device's VXLAN ID. + * + * Since: 1.2 + **/ +guint +nm_device_vxlan_get_id (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), 0); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->id; +} + +/** + * nm_device_vxlan_get_group: + * @device: a #NMDeviceVxlan + * + * Returns: The unicast destination IP address or the multicast + * IP address joined + * + * Since: 1.2 + **/ +const char * +nm_device_vxlan_get_group (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), NULL); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->group; +} + +/** + * nm_device_vxlan_get_local: + * @device: a #NMDeviceVxlan + * + * Returns: the source IP address to use in outgoing packets + * + * Since: 1.2 + **/ +const char * +nm_device_vxlan_get_local (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), NULL); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->local; +} + +/** + * nm_device_vxlan_get_src_port_min: + * @device: a #NMDeviceVxlan + * + * Returns: the minimum UDP source port + * + * Since: 1.2 + **/ +guint +nm_device_vxlan_get_src_port_min (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), 0); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->src_port_min; +} + +/** + * nm_device_vxlan_get_src_port_max: + * @device: a #NMDeviceVxlan + * + * Returns: the maximum UDP source port + * + * Since: 1.2 + **/ +guint +nm_device_vxlan_get_src_port_max (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), 0); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->src_port_max; +} + +/** + * nm_device_vxlan_get_dst_port: + * @device: a #NMDeviceVxlan + * + * Returns: the UDP destination port + * + * Since: 1.2 + **/ +guint +nm_device_vxlan_get_dst_port (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), 0); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->dst_port; +} + +/** + * nm_device_vxlan_get_learning: + * @device: a #NMDeviceVxlan + * + * Returns: whether address learning is enabled + * + * Since: 1.2 + **/ +gboolean +nm_device_vxlan_get_learning (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), FALSE); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->learning; +} + +/** + * nm_device_vxlan_get_ageing: + * @device: a #NMDeviceVxlan + * + * Returns: the lifetime in seconds of FDB entries learnt by the kernel + * + * Since: 1.2 + **/ +guint +nm_device_vxlan_get_ageing (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), 0); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->ageing; +} + +/** + * nm_device_vxlan_get_tos: + * @device: a #NMDeviceVxlan + * + * Returns: the TOS value to use in outgoing packets + * + * Since: 1.2 + **/ +guint +nm_device_vxlan_get_tos (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), 0); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->tos; +} + +/** + * nm_device_vxlan_get_ttl: + * @device: a #NMDeviceVxlan + * + * Returns: the time-to-live value to use in outgoing packets + * + * Since: 1.2 + **/ +guint +nm_device_vxlan_get_ttl (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), 0); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->ttl; +} + +/** + * nm_device_vxlan_get_limit: + * @device: a #NMDeviceVxlan + * + * Returns: the maximum number of entries that can be added to the + * forwarding table + * + * Since: 1.2 + **/ +guint +nm_device_vxlan_get_limit (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), 0); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->limit; +} + +/** + * nm_device_vxlan_get_proxy: + * @device: a #NMDeviceVxlan + * + * Returns: whether ARP proxy is turned on + * + * Since: 1.2 + **/ +gboolean +nm_device_vxlan_get_proxy (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), FALSE); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->proxy; +} + +/** + * nm_device_vxlan_get_rsc: + * @device: a #NMDeviceVxlan + * + * Returns: whether route short circuit is turned on + * + * Since: 1.2 + **/ +gboolean +nm_device_vxlan_get_rsc (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), FALSE); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->rsc; +} + +/** + * nm_device_vxlan_get_l2miss: + * @device: a #NMDeviceVxlan + * + * Returns: whether netlink LL ADDR miss notifications are generated + * + * Since: 1.2 + **/ +gboolean +nm_device_vxlan_get_l2miss (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), FALSE); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->l2miss; +} + +/** + * nm_device_vxlan_get_l3miss: + * @device: a #NMDeviceVxlan + * + * Returns: wether netlink IP ADDR miss notifications are generated + * + * Since: 1.2 + **/ +gboolean +nm_device_vxlan_get_l3miss (NMDeviceVxlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VXLAN (device), FALSE); + + return NM_DEVICE_VXLAN_GET_PRIVATE (device)->l3miss; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingVxlan *s_vxlan; + + if (!NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_VXLAN_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a VXLAN connection.")); + return FALSE; + } + + s_vxlan = nm_connection_get_setting_vxlan (connection); + if (nm_setting_vxlan_get_id (s_vxlan) != nm_device_vxlan_get_id (NM_DEVICE_VXLAN (device))) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The VXLAN identifiers of the device and the connection didn't match.")); + return FALSE; + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_VXLAN; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_vxlan_get_hw_address (NM_DEVICE_VXLAN (device)); +} + +/***********************************************************/ + +static void +nm_device_vxlan_init (NMDeviceVxlan *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_VXLAN); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_VXLAN_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_VXLAN_CARRIER, &priv->carrier }, + { NM_DEVICE_VXLAN_PARENT, &priv->parent, NULL, NM_TYPE_DEVICE }, + { NM_DEVICE_VXLAN_ID, &priv->id }, + { NM_DEVICE_VXLAN_GROUP, &priv->group }, + { NM_DEVICE_VXLAN_LOCAL, &priv->local }, + { NM_DEVICE_VXLAN_SRC_PORT_MIN, &priv->src_port_min }, + { NM_DEVICE_VXLAN_SRC_PORT_MAX, &priv->src_port_max }, + { NM_DEVICE_VXLAN_DST_PORT, &priv->dst_port }, + { NM_DEVICE_VXLAN_TOS, &priv->tos }, + { NM_DEVICE_VXLAN_TTL, &priv->ttl }, + { NM_DEVICE_VXLAN_LIMIT, &priv->limit }, + { NM_DEVICE_VXLAN_LEARNING, &priv->learning }, + { NM_DEVICE_VXLAN_AGEING, &priv->ageing }, + { NM_DEVICE_VXLAN_PROXY, &priv->proxy }, + { NM_DEVICE_VXLAN_RSC, &priv->rsc }, + { NM_DEVICE_VXLAN_L2MISS, &priv->l2miss }, + { NM_DEVICE_VXLAN_L3MISS, &priv->l3miss }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_vxlan_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_VXLAN, + property_info); +} + +static void +finalize (GObject *object) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (object); + + g_free (priv->hw_address); + g_clear_object (&priv->parent); + + G_OBJECT_CLASS (nm_device_vxlan_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceVxlan *device = NM_DEVICE_VXLAN (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_vxlan_get_hw_address (device)); + break; + case PROP_CARRIER: + g_value_set_boolean (value, nm_device_vxlan_get_carrier (device)); + break; + case PROP_PARENT: + g_value_set_object (value, nm_device_vxlan_get_parent (device)); + break; + case PROP_ID: + g_value_set_uint (value, nm_device_vxlan_get_id (device)); + break; + case PROP_GROUP: + g_value_set_string (value, nm_device_vxlan_get_group (device)); + break; + case PROP_LOCAL: + g_value_set_string (value, nm_device_vxlan_get_local (device)); + break; + case PROP_TOS: + g_value_set_uint (value, nm_device_vxlan_get_tos (device)); + break; + case PROP_TTL: + g_value_set_uint (value, nm_device_vxlan_get_ttl (device)); + break; + case PROP_LIMIT: + g_value_set_uint (value, nm_device_vxlan_get_limit (device)); + break; + case PROP_LEARNING: + g_value_set_boolean (value, nm_device_vxlan_get_learning (device)); + break; + case PROP_AGEING: + g_value_set_uint (value, nm_device_vxlan_get_ageing (device)); + break; + case PROP_DST_PORT: + g_value_set_uint (value, nm_device_vxlan_get_dst_port (device)); + break; + case PROP_SRC_PORT_MIN: + g_value_set_uint (value, nm_device_vxlan_get_src_port_min (device)); + break; + case PROP_SRC_PORT_MAX: + g_value_set_uint (value, nm_device_vxlan_get_src_port_max (device)); + break; + case PROP_PROXY: + g_value_set_boolean (value, nm_device_vxlan_get_proxy (device)); + break; + case PROP_RSC: + g_value_set_boolean (value, nm_device_vxlan_get_rsc (device)); + break; + case PROP_L2MISS: + g_value_set_boolean (value, nm_device_vxlan_get_l2miss (device)); + break; + case PROP_L3MISS: + g_value_set_boolean (value, nm_device_vxlan_get_l3miss (device)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_vxlan_class_init (NMDeviceVxlanClass *vxlan_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (vxlan_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (vxlan_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (vxlan_class); + + g_type_class_add_private (vxlan_class, sizeof (NMDeviceVxlanPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_VXLAN); + + /* virtual methods */ + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceVxlan:hw-address: + * + * The hardware (MAC) address of the device. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_VXLAN_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:carrier: + * + * Whether the device has carrier. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_VXLAN_CARRIER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:parent: + * + * The devices's parent device. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_object (NM_DEVICE_VXLAN_PARENT, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:id: + * + * The device's VXLAN ID. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_ID, + g_param_spec_uint (NM_DEVICE_VXLAN_ID, "", "", + 0, (1 << 24) - 1, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:group: + * + * The unicast destination IP address used in outgoing packets when the + * destination link layer address is not known in the VXLAN device + * forwarding database or the multicast IP address joined. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_GROUP, + g_param_spec_string (NM_DEVICE_VXLAN_GROUP, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:local: + * + * The source IP address to use in outgoing packets. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_LOCAL, + g_param_spec_string (NM_DEVICE_VXLAN_LOCAL, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:tos: + * + * The TOS value to use in outgoing packets. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_TOS, + g_param_spec_uchar (NM_DEVICE_VXLAN_TOS, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:ttl: + * + * The time-to-live value to use in outgoing packets. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_TTL, + g_param_spec_uchar (NM_DEVICE_VXLAN_TTL, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:learning: + * + * Whether unknown source link layer addresses and IP addresses are entered + * into the VXLAN device forwarding database. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_LEARNING, + g_param_spec_boolean (NM_DEVICE_VXLAN_LEARNING, "", "", + TRUE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:ageing: + * + * The lifetime in seconds of FDB entries learnt by the kernel. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_AGEING, + g_param_spec_uint (NM_DEVICE_VXLAN_AGEING, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:limit: + * + * The maximum number of entries that can be added to the forwarding table. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_LIMIT, + g_param_spec_uint (NM_DEVICE_VXLAN_LIMIT, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:dst-port: + * + * The UDP destination port used to communicate with the remote VXLAN tunnel + * endpoint. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_DST_PORT, + g_param_spec_uint (NM_DEVICE_VXLAN_DST_PORT, "", "", + 0, 65535, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:src-port-min: + * + * The minimum UDP source port used to communicate with the remote VXLAN + * tunnel endpoint. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_SRC_PORT_MIN, + g_param_spec_uint (NM_DEVICE_VXLAN_SRC_PORT_MIN, "", "", + 0, 65535, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:src-port-max: + * + * The maximum UDP source port used to communicate with the remote VXLAN + * tunnel endpoint. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_SRC_PORT_MAX, + g_param_spec_uint (NM_DEVICE_VXLAN_SRC_PORT_MAX, "", "", + 0, 65535, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:proxy: + * + * Whether ARP proxy is turned on. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_PROXY, + g_param_spec_boolean (NM_DEVICE_VXLAN_PROXY, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:rsc: + * + * Whether route short circuit is turned on. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_RSC, + g_param_spec_boolean (NM_DEVICE_VXLAN_RSC, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:l2miss: + * + * Whether netlink LL ADDR miss notifications are generated. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_L2MISS, + g_param_spec_boolean (NM_DEVICE_VXLAN_L2MISS, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVxlan:l3miss: + * + * Whether netlink IP ADDR miss notifications are generated. + * + * Since: 1.2 + */ + g_object_class_install_property + (object_class, PROP_L3MISS, + g_param_spec_boolean (NM_DEVICE_VXLAN_L3MISS, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-device-vxlan.h b/libnm/nm-device-vxlan.h new file mode 100644 index 0000000000..1fb63597e7 --- /dev/null +++ b/libnm/nm-device-vxlan.h @@ -0,0 +1,110 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_VXLAN_H__ +#define __NM_DEVICE_VXLAN_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_VXLAN (nm_device_vxlan_get_type ()) +#define NM_DEVICE_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlan)) +#define NM_DEVICE_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanClass)) +#define NM_IS_DEVICE_VXLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_VXLAN)) +#define NM_IS_DEVICE_VXLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_VXLAN)) +#define NM_DEVICE_VXLAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanClass)) + +#define NM_DEVICE_VXLAN_HW_ADDRESS "hw-address" +#define NM_DEVICE_VXLAN_CARRIER "carrier" +#define NM_DEVICE_VXLAN_PARENT "parent" +#define NM_DEVICE_VXLAN_ID "id" +#define NM_DEVICE_VXLAN_GROUP "group" +#define NM_DEVICE_VXLAN_LOCAL "local" +#define NM_DEVICE_VXLAN_SRC_PORT_MIN "src-port-min" +#define NM_DEVICE_VXLAN_SRC_PORT_MAX "src-port-max" +#define NM_DEVICE_VXLAN_LEARNING "learning" +#define NM_DEVICE_VXLAN_AGEING "ageing" +#define NM_DEVICE_VXLAN_TOS "tos" +#define NM_DEVICE_VXLAN_TTL "ttl" +#define NM_DEVICE_VXLAN_LIMIT "limit" +#define NM_DEVICE_VXLAN_PROXY "proxy" +#define NM_DEVICE_VXLAN_RSC "rsc" +#define NM_DEVICE_VXLAN_L2MISS "l2miss" +#define NM_DEVICE_VXLAN_L3MISS "l3miss" +#define NM_DEVICE_VXLAN_DST_PORT "dst-port" + +struct _NMDeviceVxlan { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceVxlanClass; + +NM_AVAILABLE_IN_1_2 +GType nm_device_vxlan_get_type (void); +NM_AVAILABLE_IN_1_2 +const char * nm_device_vxlan_get_hw_address (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +gboolean nm_device_vxlan_get_carrier (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +NMDevice * nm_device_vxlan_get_parent (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +guint nm_device_vxlan_get_id (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +const char * nm_device_vxlan_get_group (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +const char * nm_device_vxlan_get_local (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +guint nm_device_vxlan_get_src_port_min (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +guint nm_device_vxlan_get_src_port_max (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +guint nm_device_vxlan_get_dst_port (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +gboolean nm_device_vxlan_get_learning (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +guint nm_device_vxlan_get_ageing (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +guint nm_device_vxlan_get_tos (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +guint nm_device_vxlan_get_ttl (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +guint nm_device_vxlan_get_limit (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +gboolean nm_device_vxlan_get_proxy (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +gboolean nm_device_vxlan_get_rsc (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +gboolean nm_device_vxlan_get_l2miss (NMDeviceVxlan *device); +NM_AVAILABLE_IN_1_2 +gboolean nm_device_vxlan_get_l3miss (NMDeviceVxlan *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_VXLAN_H__ */ diff --git a/libnm/nm-device.c b/libnm/nm-device.c index 119e54fa0b..8efd0e68da 100644 --- a/libnm/nm-device.c +++ b/libnm/nm-device.c @@ -40,6 +40,7 @@ #include "nm-device-team.h" #include "nm-device-bridge.h" #include "nm-device-vlan.h" +#include "nm-device-vxlan.h" #include "nm-device-generic.h" #include "nm-device-ip-tunnel.h" #include "nm-device-macvlan.h" @@ -374,6 +375,8 @@ _nm_device_gtype_from_dtype (NMDeviceType dtype) return NM_TYPE_DEVICE_IP_TUNNEL; case NM_DEVICE_TYPE_MACVLAN: return NM_TYPE_DEVICE_MACVLAN; + case NM_DEVICE_TYPE_VXLAN: + return NM_TYPE_DEVICE_VXLAN; default: g_warning ("Unknown device type %d", dtype); return G_TYPE_INVALID; diff --git a/libnm/nm-types.h b/libnm/nm-types.h index 82001c0fb9..be09daaf89 100644 --- a/libnm/nm-types.h +++ b/libnm/nm-types.h @@ -44,6 +44,7 @@ typedef struct _NMDeviceOlpcMesh NMDeviceOlpcMesh; typedef struct _NMDeviceTeam NMDeviceTeam; typedef struct _NMDeviceTun NMDeviceTun; typedef struct _NMDeviceVlan NMDeviceVlan; +typedef struct _NMDeviceVxlan NMDeviceVxlan; typedef struct _NMDeviceWifi NMDeviceWifi; typedef struct _NMDeviceWimax NMDeviceWimax; typedef struct _NMDhcpConfig NMDhcpConfig; diff --git a/man/nmcli.1.in b/man/nmcli.1.in index e78c72ea32..57c4693328 100644 --- a/man/nmcli.1.in +++ b/man/nmcli.1.in @@ -694,6 +694,22 @@ The value can be prefixed with \fBifname/\fP, \fBuuid/\fP or \fBid/\fP to disamb .RE .RS .TP +.B vxlan: +.IP "\fIid \fP" 42 +\(en VXLAN Network Identifer to use +.IP "\fIremote \fP" 42 +\(en unicast destination IP address or multicast IP address to join +.IP "\fI[local ]\fP" 42 +\(en source IP address +.IP "\fI[source-port-min <0-65535>]\fP" 42 +\(en minimum UDP source port to communicate to the remote VXLAN tunnel endpoint +.IP "\fI[source-port-max <0-65535>]\fP" 42 +\(en maximum UDP source port to communicate to the remote VXLAN tunnel endpoint +.IP "\fI[destination-port <0-65535>]\fP" 42 +\(en UDP destination port to communicate to the remote VXLAN tunnel endpoint +.RE +.RS +.TP .B SLAVE_OPTIONS: .RE .RS diff --git a/po/POTFILES.in b/po/POTFILES.in index 2d1afcc3c6..9c37b7ed89 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -75,6 +75,7 @@ libnm-core/nm-setting-team-port.c libnm-core/nm-setting-tun.c libnm-core/nm-setting-vlan.c libnm-core/nm-setting-vpn.c +libnm-core/nm-setting-vxlan.c libnm-core/nm-setting-wimax.c libnm-core/nm-setting-wired.c libnm-core/nm-setting-wireless-security.c @@ -128,6 +129,7 @@ libnm/nm-device-modem.c libnm/nm-device-olpc-mesh.c libnm/nm-device-team.c libnm/nm-device-vlan.c +libnm/nm-device-vxlan.c libnm/nm-device-wifi.c libnm/nm-device-wimax.c libnm/nm-device.c @@ -157,6 +159,7 @@ src/devices/nm-device-ip-tunnel.c src/devices/nm-device-macvlan.c src/devices/nm-device-tun.c src/devices/nm-device-vlan.c +src/devices/nm-device-vxlan.c src/devices/team/nm-device-team.c src/devices/wifi/nm-device-olpc-mesh.c src/devices/wifi/nm-device-wifi.c diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index beee9f2c6c..7eabbcdb1f 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2013, 2014 Red Hat, Inc. + * Copyright 2013 - 2015 Red Hat, Inc. */ #include "config.h" @@ -29,17 +29,21 @@ #include "nm-platform.h" #include "nm-utils.h" #include "nm-device-factory.h" +#include "nm-setting-vxlan.h" +#include "nm-connection-provider.h" +#include "nm-activation-request.h" #include "nmdbus-device-vxlan.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceVxlan); -G_DEFINE_TYPE (NMDeviceVxlan, nm_device_vxlan, NM_TYPE_DEVICE_GENERIC) +G_DEFINE_TYPE (NMDeviceVxlan, nm_device_vxlan, NM_TYPE_DEVICE) #define NM_DEVICE_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanPrivate)) typedef struct { + NMDevice *parent; NMPlatformLnkVxlan props; } NMDeviceVxlanPrivate; @@ -47,16 +51,16 @@ enum { PROP_0, PROP_PARENT, PROP_ID, - PROP_GROUP, PROP_LOCAL, + PROP_GROUP, PROP_TOS, PROP_TTL, PROP_LEARNING, PROP_AGEING, PROP_LIMIT, - PROP_DST_PORT, PROP_SRC_PORT_MIN, PROP_SRC_PORT_MAX, + PROP_DST_PORT, PROP_PROXY, PROP_RSC, PROP_L2MISS, @@ -74,6 +78,7 @@ update_properties (NMDevice *device) NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); GObject *object = G_OBJECT (device); const NMPlatformLnkVxlan *props; + NMDevice *parent; props = nm_platform_link_get_lnk_vxlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); if (!props) { @@ -83,18 +88,23 @@ update_properties (NMDevice *device) g_object_freeze_notify (object); - if (priv->props.parent_ifindex != props->parent_ifindex) + if (priv->props.parent_ifindex != props->parent_ifindex) { + g_clear_object (&priv->parent); + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), props->parent_ifindex); + if (parent) + priv->parent = g_object_ref (parent); g_object_notify (object, NM_DEVICE_VXLAN_PARENT); + } if (priv->props.id != props->id) g_object_notify (object, NM_DEVICE_VXLAN_ID); - if (priv->props.group != props->group) - g_object_notify (object, NM_DEVICE_VXLAN_GROUP); if (priv->props.local != props->local) g_object_notify (object, NM_DEVICE_VXLAN_LOCAL); - if (memcmp (&priv->props.group6, &props->group6, sizeof (props->group6)) != 0) - g_object_notify (object, NM_DEVICE_VXLAN_GROUP); if (memcmp (&priv->props.local6, &props->local6, sizeof (props->local6)) != 0) g_object_notify (object, NM_DEVICE_VXLAN_LOCAL); + if (priv->props.group != props->group) + g_object_notify (object, NM_DEVICE_VXLAN_GROUP); + if (memcmp (&priv->props.group6, &props->group6, sizeof (props->group6)) != 0) + g_object_notify (object, NM_DEVICE_VXLAN_GROUP); if (priv->props.tos != props->tos) g_object_notify (object, NM_DEVICE_VXLAN_TOS); if (priv->props.ttl != props->ttl) @@ -105,12 +115,12 @@ update_properties (NMDevice *device) g_object_notify (object, NM_DEVICE_VXLAN_AGEING); if (priv->props.limit != props->limit) g_object_notify (object, NM_DEVICE_VXLAN_LIMIT); - if (priv->props.dst_port != props->dst_port) - g_object_notify (object, NM_DEVICE_VXLAN_DST_PORT); if (priv->props.src_port_min != props->src_port_min) g_object_notify (object, NM_DEVICE_VXLAN_SRC_PORT_MIN); if (priv->props.src_port_max != props->src_port_max) g_object_notify (object, NM_DEVICE_VXLAN_SRC_PORT_MAX); + if (priv->props.dst_port != props->dst_port) + g_object_notify (object, NM_DEVICE_VXLAN_DST_PORT); if (priv->props.proxy != props->proxy) g_object_notify (object, NM_DEVICE_VXLAN_PROXY); if (priv->props.rsc != props->rsc) @@ -160,6 +170,352 @@ unrealize (NMDevice *device, gboolean remove_resources) g_free (properties); } +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + NMPlatformLink *out_plink, + GError **error) +{ + const char *iface = nm_device_get_iface (device); + NMPlatformError plerr; + NMPlatformLnkVxlan props = { }; + NMSettingVxlan *s_vxlan; + const char *str; + int ret; + + s_vxlan = nm_connection_get_setting_vxlan (connection); + g_assert (s_vxlan); + g_assert (out_plink); + + if (parent) + props.parent_ifindex = nm_device_get_ifindex (parent); + + props.id = nm_setting_vxlan_get_id (s_vxlan); + + str = nm_setting_vxlan_get_local (s_vxlan); + if (str) { + ret = inet_pton (AF_INET, str, &props.local); + if (ret != 1) + ret = inet_pton (AF_INET6, str, &props.local6); + if (ret != 1) + return FALSE; + } + + str = nm_setting_vxlan_get_remote (s_vxlan); + ret = inet_pton (AF_INET, str, &props.group); + if (ret != 1) + ret = inet_pton (AF_INET6, str, &props.group6); + if (ret != 1) + return FALSE; + + props.tos = nm_setting_vxlan_get_tos (s_vxlan); + props.ttl = nm_setting_vxlan_get_ttl (s_vxlan); + props.learning = nm_setting_vxlan_get_learning (s_vxlan); + props.ageing = nm_setting_vxlan_get_ageing (s_vxlan); + props.limit = nm_setting_vxlan_get_limit (s_vxlan); + props.src_port_min = nm_setting_vxlan_get_source_port_min (s_vxlan); + props.src_port_max = nm_setting_vxlan_get_source_port_max (s_vxlan); + props.dst_port = nm_setting_vxlan_get_destination_port (s_vxlan); + props.proxy = nm_setting_vxlan_get_proxy (s_vxlan); + props.rsc = nm_setting_vxlan_get_rsc (s_vxlan); + props.l2miss = nm_setting_vxlan_get_l2_miss (s_vxlan); + props.l3miss = nm_setting_vxlan_get_l3_miss (s_vxlan); + + plerr = nm_platform_link_vxlan_add (NM_PLATFORM_GET, iface, &props, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create VXLAN interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + + return TRUE; +} + +static gboolean +realize (NMDevice *device, NMPlatformLink *plink, GError **error) +{ + g_assert (plink->type == NM_LINK_TYPE_VXLAN); + + update_properties (device); + + return TRUE; +} + +static gboolean +match_parent (NMDeviceVxlan *self, const char *parent) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (self); + + g_return_val_if_fail (parent != NULL, FALSE); + + if (!priv->parent) + return FALSE; + + if (nm_utils_is_uuid (parent)) { + NMActRequest *parent_req; + NMConnection *parent_connection; + + /* If the parent is a UUID, the connection matches if our parent + * device has that connection activated. + */ + parent_req = nm_device_get_act_request (priv->parent); + if (!parent_req) + return FALSE; + + parent_connection = nm_active_connection_get_applied_connection (NM_ACTIVE_CONNECTION (parent_req)); + if (!parent_connection) + return FALSE; + + if (g_strcmp0 (parent, nm_connection_get_uuid (parent_connection)) != 0) + return FALSE; + } else { + /* interface name */ + if (g_strcmp0 (parent, nm_device_get_ip_iface (priv->parent)) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +address_matches (const char *str, in_addr_t addr4, struct in6_addr *addr6) +{ + in_addr_t new_addr4 = 0; + struct in6_addr new_addr6 = { }; + + if (!str) { + return addr4 == 0 + && !memcmp (addr6, &in6addr_any, sizeof (in6addr_any)); + } + + if (inet_pton (AF_INET, str, &new_addr4) == 1) + return new_addr4 == addr4; + else if (inet_pton (AF_INET6, str, &new_addr6) == 1) + return !memcmp (&new_addr6, addr6, sizeof (new_addr6)); + else + return FALSE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); + NMSettingVxlan *s_vxlan; + const char *iface, *parent; + + if (!NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_vxlan = nm_connection_get_setting_vxlan (connection); + if (!s_vxlan) + return FALSE; + + iface = nm_connection_get_interface_name (connection); + if (iface) { + if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0) + return FALSE; + } + + if (nm_device_is_real (device)) { + parent = nm_setting_vxlan_get_parent (s_vxlan); + if ( parent + && !match_parent (NM_DEVICE_VXLAN (device), parent)) + return FALSE; + + if (priv->props.id != nm_setting_vxlan_get_id (s_vxlan)) + return FALSE; + + if (!address_matches (nm_setting_vxlan_get_local (s_vxlan), priv->props.local, &priv->props.local6)) + return FALSE; + + if (!address_matches (nm_setting_vxlan_get_remote (s_vxlan), priv->props.group, &priv->props.group6)) + return FALSE; + + if (priv->props.src_port_min != nm_setting_vxlan_get_source_port_min (s_vxlan)) + return FALSE; + + if (priv->props.src_port_max != nm_setting_vxlan_get_source_port_max (s_vxlan)) + return FALSE; + + if (priv->props.dst_port != nm_setting_vxlan_get_destination_port (s_vxlan)) + return FALSE; + + if (priv->props.tos != nm_setting_vxlan_get_tos (s_vxlan)) + return FALSE; + + if (priv->props.ttl != nm_setting_vxlan_get_ttl (s_vxlan)) + return FALSE; + + if (priv->props.learning != nm_setting_vxlan_get_learning (s_vxlan)) + return FALSE; + + if (priv->props.ageing != nm_setting_vxlan_get_ageing (s_vxlan)) + return FALSE; + + if (priv->props.proxy != nm_setting_vxlan_get_proxy (s_vxlan)) + return FALSE; + + if (priv->props.rsc != nm_setting_vxlan_get_rsc (s_vxlan)) + return FALSE; + + if (priv->props.l2miss != nm_setting_vxlan_get_l2_miss (s_vxlan)) + return FALSE; + + if (priv->props.l3miss != nm_setting_vxlan_get_l3_miss (s_vxlan)) + return FALSE; + } + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingVxlan *s_vxlan; + + nm_utils_complete_generic (connection, + NM_SETTING_VXLAN_SETTING_NAME, + existing_connections, + NULL, + _("VXLAN connection"), + NULL, + TRUE); + + s_vxlan = nm_connection_get_setting_vxlan (connection); + if (!s_vxlan) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'vxlan' setting is required."); + return FALSE; + } + + return TRUE; +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); + NMSettingVxlan *s_vxlan = nm_connection_get_setting_vxlan (connection); + NMDevice *parent = NULL; + const char *setting_parent, *new_parent; + + if (!s_vxlan) { + s_vxlan = (NMSettingVxlan *) nm_setting_vxlan_new (); + nm_connection_add_setting (connection, (NMSetting *) s_vxlan); + } + + if (priv->props.id != nm_setting_vxlan_get_id (s_vxlan)) + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_ID, priv->props.id, NULL); + + if (priv->props.parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS) + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); + + /* Update parent in the connection; default to parent's interface name */ + if (parent) { + new_parent = nm_device_get_iface (parent); + setting_parent = nm_setting_vxlan_get_parent (s_vxlan); + if (setting_parent && nm_utils_is_uuid (setting_parent)) { + NMConnection *parent_connection; + + /* Don't change a parent specified by UUID if it's still valid */ + parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), + setting_parent); + if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) + new_parent = NULL; + } + if (new_parent) + g_object_set (s_vxlan, NM_SETTING_VXLAN_PARENT, new_parent, NULL); + } else + g_object_set (s_vxlan, NM_SETTING_VXLAN_PARENT, NULL, NULL); + + if (!address_matches (nm_setting_vxlan_get_remote (s_vxlan), priv->props.group, &priv->props.group6)) { + if (priv->props.group) { + g_object_set (s_vxlan, NM_SETTING_VXLAN_REMOTE, + nm_utils_inet4_ntop (priv->props.group, NULL), + NULL); + } else { + g_object_set (s_vxlan, NM_SETTING_VXLAN_REMOTE, + nm_utils_inet6_ntop (&priv->props.group6, NULL), + NULL); + } + } + + if (!address_matches (nm_setting_vxlan_get_local (s_vxlan), priv->props.local, &priv->props.local6)) { + if (priv->props.local) { + g_object_set (s_vxlan, NM_SETTING_VXLAN_LOCAL, + nm_utils_inet4_ntop (priv->props.local, NULL), + NULL); + } else if (memcmp (&priv->props.local6, &in6addr_any, sizeof (in6addr_any))) { + g_object_set (s_vxlan, NM_SETTING_VXLAN_LOCAL, + nm_utils_inet6_ntop (&priv->props.local6, NULL), + NULL); + } + } + + if (priv->props.src_port_min != nm_setting_vxlan_get_source_port_min (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_SOURCE_PORT_MIN, + priv->props.src_port_min, NULL); + } + + if (priv->props.src_port_max != nm_setting_vxlan_get_source_port_max (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_SOURCE_PORT_MAX, + priv->props.src_port_max, NULL); + } + + if (priv->props.dst_port != nm_setting_vxlan_get_destination_port (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_DESTINATION_PORT, + priv->props.dst_port, NULL); + } + + if (priv->props.tos != nm_setting_vxlan_get_tos (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_TOS, + priv->props.tos, NULL); + } + + if (priv->props.ttl != nm_setting_vxlan_get_ttl (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_TTL, + priv->props.ttl, NULL); + } + + if (priv->props.learning != nm_setting_vxlan_get_learning (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_LEARNING, + priv->props.learning, NULL); + } + + if (priv->props.ageing != nm_setting_vxlan_get_ageing (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_AGEING, + priv->props.ageing, NULL); + } + + if (priv->props.proxy != nm_setting_vxlan_get_proxy (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_PROXY, + priv->props.proxy, NULL); + } + + if (priv->props.rsc != nm_setting_vxlan_get_rsc (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_RSC, + priv->props.rsc, NULL); + } + + if (priv->props.l2miss != nm_setting_vxlan_get_l2_miss (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_L2_MISS, + priv->props.l2miss, NULL); + } + + if (priv->props.l3miss != nm_setting_vxlan_get_l3_miss (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_L3_MISS, + priv->props.l3miss, NULL); + } +} + /**************************************************************/ static void @@ -236,6 +592,15 @@ get_property (GObject *object, guint prop_id, } } +static void +dispose (GObject *object) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (object); + + g_clear_object (&priv->parent); + G_OBJECT_CLASS (nm_device_vxlan_parent_class)->dispose (object); +} + static void nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) { @@ -247,10 +612,17 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VXLAN) object_class->get_property = get_property; + object_class->dispose = dispose; device_class->link_changed = link_changed; device_class->setup_start = setup_start; device_class->unrealize = unrealize; + device_class->connection_type = NM_SETTING_VXLAN_SETTING_NAME; + device_class->create_and_realize = create_and_realize; + device_class->realize = realize; + device_class->check_connection_compatible = check_connection_compatible; + device_class->complete_connection = complete_connection; + device_class->update_connection = update_connection; /* properties */ g_object_class_install_property @@ -268,15 +640,15 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_GROUP, - g_param_spec_string (NM_DEVICE_VXLAN_GROUP, "", "", + (object_class, PROP_LOCAL, + g_param_spec_string (NM_DEVICE_VXLAN_LOCAL, "", "", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_LOCAL, - g_param_spec_string (NM_DEVICE_VXLAN_LOCAL, "", "", + (object_class, PROP_GROUP, + g_param_spec_string (NM_DEVICE_VXLAN_GROUP, "", "", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); @@ -316,13 +688,6 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property - (object_class, PROP_DST_PORT, - g_param_spec_uint (NM_DEVICE_VXLAN_DST_PORT, "", "", - 0, 65535, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, PROP_SRC_PORT_MIN, g_param_spec_uint (NM_DEVICE_VXLAN_SRC_PORT_MIN, "", "", @@ -337,6 +702,13 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_DST_PORT, + g_param_spec_uint (NM_DEVICE_VXLAN_DST_PORT, "", "", + 0, 65535, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_PROXY, g_param_spec_boolean (NM_DEVICE_VXLAN_PROXY, "", "", @@ -385,13 +757,49 @@ create_device (NMDeviceFactory *factory, return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VXLAN, NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "Vxlan", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VXLAN, NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_VXLAN, NULL); } +static const char * +get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) +{ + NMSettingVxlan *s_vxlan; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_VXLAN_SETTING_NAME), NULL); + + s_vxlan = nm_connection_get_setting_vxlan (connection); + g_assert (s_vxlan); + + return nm_setting_vxlan_get_parent (s_vxlan); +} + +static char * +get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) +{ + const char *ifname; + NMSettingVxlan *s_vxlan; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_VXLAN_SETTING_NAME), NULL); + + s_vxlan = nm_connection_get_setting_vxlan (connection); + g_assert (s_vxlan); + + if (nm_setting_vxlan_get_parent (s_vxlan) && !parent_iface) + return NULL; + + ifname = nm_connection_get_interface_name (connection); + return g_strdup (ifname); +} + NM_DEVICE_FACTORY_DEFINE_INTERNAL (VXLAN, Vxlan, vxlan, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VXLAN), + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VXLAN) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_VXLAN_SETTING_NAME), factory_iface->create_device = create_device; + factory_iface->get_connection_parent = get_connection_parent; + factory_iface->get_virtual_iface_name = get_virtual_iface_name; ) diff --git a/src/devices/nm-device-vxlan.h b/src/devices/nm-device-vxlan.h index 9db78cdfcb..7de04a1242 100644 --- a/src/devices/nm-device-vxlan.h +++ b/src/devices/nm-device-vxlan.h @@ -49,8 +49,8 @@ G_BEGIN_DECLS #define NM_DEVICE_VXLAN_L2MISS "l2miss" #define NM_DEVICE_VXLAN_L3MISS "l3miss" -typedef NMDeviceGeneric NMDeviceVxlan; -typedef NMDeviceGenericClass NMDeviceVxlanClass; +typedef NMDevice NMDeviceVxlan; +typedef NMDeviceClass NMDeviceVxlanClass; GType nm_device_vxlan_get_type (void); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index dd8f698d52..8b9c52f3db 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -787,6 +787,8 @@ nm_device_get_priority (NMDevice *self) return 425; case NM_DEVICE_TYPE_TUN: return 450; + case NM_DEVICE_TYPE_VXLAN: + return 500; case NM_DEVICE_TYPE_WIFI: return 600; case NM_DEVICE_TYPE_OLPC_MESH: diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 973df29a6e..09327a4d81 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -708,6 +708,31 @@ link_vlan_change (NMPlatform *platform, return FALSE; } +static gboolean +link_vxlan_add (NMPlatform *platform, + const char *name, + NMPlatformLnkVxlan *props, + NMPlatformLink *out_link) +{ + NMFakePlatformLink *device; + + if (!link_add (platform, name, NM_LINK_TYPE_VXLAN, NULL, 0, NULL)) + return FALSE; + + device = link_get (platform, nm_platform_link_get_ifindex (platform, name)); + + g_return_val_if_fail (device, FALSE); + g_return_val_if_fail (!device->lnk, FALSE); + + device->lnk = nmp_object_new (NMP_OBJECT_TYPE_LNK_VXLAN, NULL); + device->lnk->lnk_vxlan = *props; + device->link.parent = props->parent_ifindex; + + if (out_link) + *out_link = device->link; + return TRUE; +} + static gboolean infiniband_partition_add (NMPlatform *platform, int parent, int p_key, NMPlatformLink *out_link) { @@ -1458,6 +1483,7 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass) platform_class->vlan_add = vlan_add; platform_class->link_vlan_change = link_vlan_change; + platform_class->link_vxlan_add = link_vxlan_add; platform_class->infiniband_partition_add = infiniband_partition_add; diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index d7417b76d6..730f4b1c86 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -4466,6 +4467,80 @@ nla_put_failure: g_return_val_if_reached (FALSE); } +static gboolean +link_vxlan_add (NMPlatform *platform, + const char *name, + NMPlatformLnkVxlan *props, + NMPlatformLink *out_link) +{ + nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + struct nlattr *info; + struct nlattr *data; + struct nm_ifla_vxlan_port_range port_range; + + g_return_val_if_fail (props, FALSE); + + _LOGD ("link: add vxlan '%s', parent %d, vxlan id %d", + name, props->parent_ifindex, props->id); + + nlmsg = _nl_msg_new_link (RTM_NEWLINK, + NLM_F_CREATE, + 0, + name, + 0, + 0); + if (!nlmsg) + return FALSE; + + if (!(info = nla_nest_start (nlmsg, IFLA_LINKINFO))) + goto nla_put_failure; + + NLA_PUT_STRING (nlmsg, IFLA_INFO_KIND, "vxlan"); + + if (!(data = nla_nest_start (nlmsg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32 (nlmsg, IFLA_VXLAN_ID, props->id); + + if (props->group) + NLA_PUT (nlmsg, IFLA_VXLAN_GROUP, sizeof (props->group), &props->group); + else if (memcmp (&props->group6, &in6addr_any, sizeof (in6addr_any))) + NLA_PUT (nlmsg, IFLA_VXLAN_GROUP6, sizeof (props->group6), &props->group6); + + if (props->local) + NLA_PUT (nlmsg, IFLA_VXLAN_LOCAL, sizeof (props->local), &props->local); + else if (memcmp (&props->local6, &in6addr_any, sizeof (in6addr_any))) + NLA_PUT (nlmsg, IFLA_VXLAN_LOCAL6, sizeof (props->local6), &props->local6); + + if (props->parent_ifindex >= 0) + NLA_PUT_U32 (nlmsg, IFLA_VXLAN_LINK, props->parent_ifindex); + + if (props->src_port_min || props->src_port_max) { + port_range.low = htons (props->src_port_min); + port_range.high = htons (props->src_port_max); + NLA_PUT (nlmsg, IFLA_VXLAN_PORT_RANGE, sizeof (port_range), &port_range); + } + + NLA_PUT_U16 (nlmsg, IFLA_VXLAN_PORT, htons (props->dst_port)); + NLA_PUT_U8 (nlmsg, IFLA_VXLAN_TOS, props->tos); + NLA_PUT_U8 (nlmsg, IFLA_VXLAN_TTL, props->ttl); + NLA_PUT_U32 (nlmsg, IFLA_VXLAN_AGEING, props->ageing); + NLA_PUT_U32 (nlmsg, IFLA_VXLAN_LIMIT, props->limit); + NLA_PUT_U8 (nlmsg, IFLA_VXLAN_LEARNING, !!props->learning); + NLA_PUT_U8 (nlmsg, IFLA_VXLAN_PROXY, !!props->proxy); + NLA_PUT_U8 (nlmsg, IFLA_VXLAN_RSC, !!props->rsc); + NLA_PUT_U8 (nlmsg, IFLA_VXLAN_L2MISS, !!props->l2miss); + NLA_PUT_U8 (nlmsg, IFLA_VXLAN_L3MISS, !!props->l3miss); + + nla_nest_end (nlmsg, data); + nla_nest_end (nlmsg, info); + + return do_add_link_with_lookup (platform, NM_LINK_TYPE_VXLAN, name, nlmsg, out_link); + +nla_put_failure: + g_return_val_if_reached (FALSE); +} + static void _vlan_change_vlan_qos_mapping_create (gboolean is_ingress_map, gboolean reset_all, @@ -5899,6 +5974,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->vlan_add = vlan_add; platform_class->link_vlan_change = link_vlan_change; + platform_class->link_vxlan_add = link_vxlan_add; platform_class->tun_add = tun_add; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index f4e24d78e1..fe42465c77 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1559,6 +1559,38 @@ nm_platform_vlan_add (NMPlatform *self, return NM_PLATFORM_ERROR_SUCCESS; } +/** + * nm_platform_link_vxlan_add: + * @self: platform instance + * @name: New interface name + * @props: properties of the new link + * @out_link: on success, the link object + * + * Create a VXLAN device. + */ +NMPlatformError +nm_platform_link_vxlan_add (NMPlatform *self, + const char *name, + NMPlatformLnkVxlan *props, + NMPlatformLink *out_link) +{ + NMPlatformError plerr; + + _CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG); + + g_return_val_if_fail (props, NM_PLATFORM_ERROR_BUG); + + plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_VXLAN, out_link); + if (plerr != NM_PLATFORM_ERROR_SUCCESS) + return plerr; + + _LOGD ("link: adding vxlan '%s' parent %d id %d", + name, props->parent_ifindex, props->id); + if (!klass->link_vxlan_add (self, name, props, out_link)) + return NM_PLATFORM_ERROR_UNSPECIFIED; + return NM_PLATFORM_ERROR_SUCCESS; +} + /** * nm_platform_tun_add: * @self: platform instance @@ -1596,7 +1628,6 @@ nm_platform_tun_add (NMPlatform *self, const char *name, gboolean tap, return NM_PLATFORM_ERROR_SUCCESS; } - gboolean nm_platform_master_set_option (NMPlatform *self, int ifindex, const char *option, const char *value) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index de20e842a3..cef962c29c 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -561,6 +561,8 @@ typedef struct { gboolean egress_reset_all, const NMVlanQosMapping *egress_map, gsize n_egress_map); + gboolean (*link_vxlan_add) (NMPlatform *, const char *name, NMPlatformLnkVxlan *props, + NMPlatformLink *out_link); gboolean (*link_gre_add) (NMPlatform *, const char *name, NMPlatformLnkGre *props, NMPlatformLink *out_link); @@ -785,6 +787,7 @@ gboolean nm_platform_link_vlan_change (NMPlatform *self, const NMVlanQosMapping *egress_map, gsize n_egress_map); +NMPlatformError nm_platform_link_vxlan_add (NMPlatform *self, const char *name, NMPlatformLnkVxlan *props, NMPlatformLink *out_link); NMPlatformError nm_platform_tun_add (NMPlatform *self, const char *name, gboolean tap, gint64 owner, gint64 group, gboolean pi, gboolean vnet_hdr, gboolean multi_queue, NMPlatformLink *out_link); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index f593c9cb80..a578a30884 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -838,6 +838,49 @@ nmtstp_link_sit_add (gboolean external_command, const char *name, NMPlatformLnkS return success; } +gboolean +nmtstp_link_vxlan_add (gboolean external_command, const char *name, NMPlatformLnkVxlan *lnk) +{ + gboolean success; + + external_command = nmtstp_run_command_check_external (external_command); + + if (external_command) { + gs_free char *dev = NULL; + gs_free char *local = NULL, *remote = NULL; + + if (lnk->parent_ifindex) + dev = g_strdup_printf ("dev %s", nm_platform_link_get_name (NM_PLATFORM_GET, lnk->parent_ifindex)); + + if (lnk->local) + local = g_strdup_printf ("%s", nm_utils_inet4_ntop (lnk->local, NULL)); + else if (memcmp (&lnk->local6, &in6addr_any, sizeof (in6addr_any))) + local = g_strdup_printf ("%s", nm_utils_inet6_ntop (&lnk->local6, NULL)); + + if (lnk->group) + remote = g_strdup_printf ("%s", nm_utils_inet4_ntop (lnk->group, NULL)); + else if (memcmp (&lnk->group6, &in6addr_any, sizeof (in6addr_any))) + remote = g_strdup_printf ("%s", nm_utils_inet6_ntop (&lnk->group6, NULL)); + + success = !nmtstp_run_command ("ip link add %s type vxlan id %u %s local %s group %s ttl %u tos %02x dstport %u srcport %u %u ageing %u", + name, + lnk->id, + dev ? dev : "", + local, + remote, + lnk->ttl, + lnk->tos, + lnk->dst_port, + lnk->src_port_min, lnk->src_port_max, + lnk->ageing); + if (success) + nmtstp_assert_wait_for_link (name, NM_LINK_TYPE_VXLAN, 100); + } else + success = nm_platform_link_vxlan_add (NM_PLATFORM_GET, name, lnk, NULL) == NM_PLATFORM_ERROR_SUCCESS; + + return success; +} + void nmtstp_ip4_address_add (gboolean external_command, int ifindex, diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index b1adfc46ba..2833a78da8 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -150,6 +150,9 @@ gboolean nmtstp_link_macvlan_add (gboolean external_command, gboolean nmtstp_link_sit_add (gboolean external_command, const char *name, NMPlatformLnkSit *lnk); +gboolean nmtstp_link_vxlan_add (gboolean external_command, + const char *name, + NMPlatformLnkVxlan *lnk); void init_tests (int *argc, char ***argv); void setup_tests (void); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 47e1af48b2..9da6bff7fa 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -669,8 +669,8 @@ test_software_detect (gconstpointer user_data) NMPlatformLnkGre lnk_gre = { }; gboolean gracefully_skip = FALSE; - inet_pton (AF_INET, "192.168.233.204", &lnk_gre.local); - inet_pton (AF_INET, "172.168.10.25", &lnk_gre.remote); + lnk_gre.local = nmtst_inet4_from_string ("192.168.233.204"); + lnk_gre.remote = nmtst_inet4_from_string ("172.168.10.25"); lnk_gre.parent_ifindex = ifindex_parent; lnk_gre.ttl = 174; lnk_gre.tos = 37; @@ -699,8 +699,8 @@ test_software_detect (gconstpointer user_data) gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ipip", NULL) != 0; } - inet_pton (AF_INET, "1.2.3.4", &lnk_ipip.local); - inet_pton (AF_INET, "5.6.7.8", &lnk_ipip.remote); + lnk_ipip.local = nmtst_inet4_from_string ("1.2.3.4"); + lnk_ipip.remote = nmtst_inet4_from_string ("5.6.7.8"); lnk_ipip.parent_ifindex = ifindex_parent; lnk_ipip.tos = 32; lnk_ipip.path_mtu_discovery = FALSE; @@ -723,8 +723,8 @@ test_software_detect (gconstpointer user_data) gracefully_skip = nm_utils_modprobe (NULL, TRUE, "ip6_tunnel", NULL) != 0; } - inet_pton (AF_INET6, "fd01::15", &lnk_ip6tnl.local); - inet_pton (AF_INET6, "fd01::16", &lnk_ip6tnl.remote); + lnk_ip6tnl.local = *nmtst_inet6_from_string ("fd01::15"); + lnk_ip6tnl.remote = *nmtst_inet6_from_string ("fd01::16"); lnk_ip6tnl.parent_ifindex = ifindex_parent; lnk_ip6tnl.tclass = 20; lnk_ip6tnl.encap_limit = 6; @@ -766,8 +766,8 @@ test_software_detect (gconstpointer user_data) NMPlatformLnkSit lnk_sit = { }; gboolean gracefully_skip = FALSE; - inet_pton (AF_INET, "192.168.200.1", &lnk_sit.local); - inet_pton (AF_INET, "172.25.100.14", &lnk_sit.remote); + lnk_sit.local = nmtst_inet4_from_string ("192.168.200.1"); + lnk_sit.remote = nmtst_inet4_from_string ("172.25.100.14"); lnk_sit.parent_ifindex = ifindex_parent; lnk_sit.ttl = 0; lnk_sit.tos = 31; @@ -790,22 +790,37 @@ test_software_detect (gconstpointer user_data) case NM_LINK_TYPE_VLAN: nmtstp_run_command_check ("ip link add name %s link %s type vlan id 1242", DEVICE_NAME, PARENT_NAME); break; - case NM_LINK_TYPE_VXLAN: + case NM_LINK_TYPE_VXLAN: { + NMPlatformLnkVxlan lnk_vxlan = { }; + switch (test_data->test_mode) { case 0: - if (nmtstp_run_command ("ip link add %s type vxlan id 42 local 23.1.2.164 group 239.1.2.134 dev %s ageing 1245 dstport 4789", DEVICE_NAME, PARENT_NAME)) { - g_test_skip ("could not add a vxlan"); - goto out_delete_parent; - } + lnk_vxlan.parent_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, PARENT_NAME); + lnk_vxlan.id = 42; + lnk_vxlan.local = nmtst_inet4_from_string ("23.1.2.164"); + lnk_vxlan.group = nmtst_inet4_from_string ("239.1.2.134"); + lnk_vxlan.dst_port = 4789; + lnk_vxlan.learning = TRUE; + lnk_vxlan.ageing = 1245; break; case 1: - if (nmtstp_run_command ("ip link add %s type vxlan id 11214423 local 1:2:3:4:334:23::23 group ff0e::115 dev %s ageing 3245 dstport 57412", DEVICE_NAME, PARENT_NAME)) { - g_test_skip ("could not add a vxlan"); - goto out_delete_parent; - } + lnk_vxlan.parent_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, PARENT_NAME); + lnk_vxlan.id = 11214423; + lnk_vxlan.local6 = *nmtst_inet6_from_string ("1:2:3:4:334:23::23"); + lnk_vxlan.group6 = *nmtst_inet6_from_string ("ff0e::115"); + lnk_vxlan.ttl = 32; + lnk_vxlan.dst_port = 57412; + lnk_vxlan.src_port_min = 1000; + lnk_vxlan.src_port_max = 1003; + lnk_vxlan.learning = TRUE; + lnk_vxlan.ageing = 3245; break; } + + if (!nmtstp_link_vxlan_add (EX, DEVICE_NAME, &lnk_vxlan)) + g_error ("Failed adding VXLAN link"); break; + } default: g_assert_not_reached (); } @@ -922,11 +937,8 @@ test_software_detect (gconstpointer user_data) g_assert (plnk == nm_platform_link_get_lnk_vxlan (NM_PLATFORM_GET, ifindex, NULL)); g_assert_cmpint (plnk->parent_ifindex, !=, 0); g_assert_cmpint (plnk->tos, ==, 0); - g_assert_cmpint (plnk->ttl, ==, 0); g_assert_cmpint (plnk->learning, ==, TRUE); g_assert_cmpint (plnk->limit, ==, 0); - g_assert_cmpint (plnk->src_port_min, ==, 0); - g_assert_cmpint (plnk->src_port_max, ==, 0); g_assert_cmpint (plnk->proxy, ==, FALSE); g_assert_cmpint (plnk->rsc, ==, FALSE); g_assert_cmpint (plnk->l2miss, ==, FALSE); @@ -939,8 +951,11 @@ test_software_detect (gconstpointer user_data) nmtst_assert_ip4_address (plnk->group, "239.1.2.134"); nmtst_assert_ip6_address (&plnk->group6, "::"); nmtst_assert_ip6_address (&plnk->local6, "::"); + g_assert_cmpint (plnk->ttl, ==, 0); g_assert_cmpint (plnk->ageing, ==, 1245); g_assert_cmpint (plnk->dst_port, ==, 4789); + g_assert_cmpint (plnk->src_port_min, ==, 0); + g_assert_cmpint (plnk->src_port_max, ==, 0); break; case 1: g_assert_cmpint (plnk->id, ==, 11214423); @@ -950,6 +965,9 @@ test_software_detect (gconstpointer user_data) nmtst_assert_ip6_address (&plnk->local6, "1:2:3:4:334:23::23"); g_assert_cmpint (plnk->ageing, ==, 3245); g_assert_cmpint (plnk->dst_port, ==, 57412); + g_assert_cmpint (plnk->ttl, ==, 32); + g_assert_cmpint (plnk->src_port_min, ==, 1000); + g_assert_cmpint (plnk->src_port_max, ==, 1003); break; } break;