LCOV - code coverage report
Current view: top level - network/netdev - geneve.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 176 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 11 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <net/if.h>
       4             : 
       5             : #include "sd-netlink.h"
       6             : 
       7             : #include "alloc-util.h"
       8             : #include "conf-parser.h"
       9             : #include "extract-word.h"
      10             : #include "geneve.h"
      11             : #include "netlink-util.h"
      12             : #include "parse-util.h"
      13             : #include "string-table.h"
      14             : #include "string-util.h"
      15             : #include "strv.h"
      16             : #include "missing.h"
      17             : #include "networkd-manager.h"
      18             : 
      19             : #define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU
      20             : #define DEFAULT_GENEVE_DESTINATION_PORT 6081
      21             : 
      22             : static const char* const geneve_df_table[_NETDEV_GENEVE_DF_MAX] = {
      23             :         [NETDEV_GENEVE_DF_NO] = "no",
      24             :         [NETDEV_GENEVE_DF_YES] = "yes",
      25             :         [NETDEV_GENEVE_DF_INHERIT] = "inherit",
      26             : };
      27             : 
      28           0 : DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(geneve_df, GeneveDF, NETDEV_GENEVE_DF_YES);
      29           0 : DEFINE_CONFIG_PARSE_ENUM(config_parse_geneve_df, geneve_df, GeneveDF, "Failed to parse Geneve IPDoNotFragment= setting");
      30             : 
      31             : /* callback for geneve netdev's created without a backing Link */
      32           0 : static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
      33             :         int r;
      34             : 
      35           0 :         assert(netdev);
      36           0 :         assert(netdev->state != _NETDEV_STATE_INVALID);
      37             : 
      38           0 :         r = sd_netlink_message_get_errno(m);
      39           0 :         if (r == -EEXIST)
      40           0 :                 log_netdev_info(netdev, "Geneve netdev exists, using existing without changing its parameters");
      41           0 :         else if (r < 0) {
      42           0 :                 log_netdev_warning_errno(netdev, r, "Geneve netdev could not be created: %m");
      43           0 :                 netdev_drop(netdev);
      44             : 
      45           0 :                 return 1;
      46             :         }
      47             : 
      48           0 :         log_netdev_debug(netdev, "Geneve created");
      49             : 
      50           0 :         return 1;
      51             : }
      52             : 
      53           0 : static int netdev_geneve_create(NetDev *netdev) {
      54           0 :         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
      55             :         Geneve *v;
      56             :         int r;
      57             : 
      58           0 :         assert(netdev);
      59             : 
      60           0 :         v = GENEVE(netdev);
      61             : 
      62           0 :         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
      63           0 :         if (r < 0)
      64           0 :                 return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m");
      65             : 
      66           0 :         r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname);
      67           0 :         if (r < 0)
      68           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m");
      69             : 
      70           0 :         if (netdev->mac) {
      71           0 :                 r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
      72           0 :                 if (r < 0)
      73           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m");
      74             :         }
      75             : 
      76           0 :         if (netdev->mtu != 0) {
      77           0 :                 r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu);
      78           0 :                 if (r < 0)
      79           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m");
      80             :         }
      81             : 
      82           0 :         r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
      83           0 :         if (r < 0)
      84           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
      85             : 
      86           0 :         r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind));
      87           0 :         if (r < 0)
      88           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
      89             : 
      90           0 :         if (v->id <= GENEVE_VID_MAX) {
      91           0 :                 r = sd_netlink_message_append_u32(m, IFLA_GENEVE_ID, v->id);
      92           0 :                 if (r < 0)
      93           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_ID attribute: %m");
      94             :         }
      95             : 
      96           0 :         if (in_addr_is_null(v->remote_family, &v->remote) == 0) {
      97           0 :                 if (v->remote_family == AF_INET)
      98           0 :                         r = sd_netlink_message_append_in_addr(m, IFLA_GENEVE_REMOTE, &v->remote.in);
      99             :                 else
     100           0 :                         r = sd_netlink_message_append_in6_addr(m, IFLA_GENEVE_REMOTE6, &v->remote.in6);
     101           0 :                 if (r < 0)
     102           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_REMOTE/IFLA_GENEVE_REMOTE6 attribute: %m");
     103             :         }
     104             : 
     105           0 :         if (v->inherit) {
     106           0 :                 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL_INHERIT, 1);
     107           0 :                 if (r < 0)
     108           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL_INHERIT attribute: %m");
     109             :         } else {
     110           0 :                 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL, v->ttl);
     111           0 :                 if (r < 0)
     112           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL attribute: %m");
     113             :         }
     114             : 
     115           0 :         r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TOS, v->tos);
     116           0 :         if (r < 0)
     117           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TOS attribute: %m");
     118             : 
     119           0 :         r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_CSUM, v->udpcsum);
     120           0 :         if (r < 0)
     121           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_CSUM attribute: %m");
     122             : 
     123           0 :         r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx);
     124           0 :         if (r < 0)
     125           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_TX attribute: %m");
     126             : 
     127           0 :         r = sd_netlink_message_append_u8(m, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx);
     128           0 :         if (r < 0)
     129           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_UDP_ZERO_CSUM6_RX attribute: %m");
     130             : 
     131           0 :         if (v->dest_port != DEFAULT_GENEVE_DESTINATION_PORT) {
     132           0 :                 r = sd_netlink_message_append_u16(m, IFLA_GENEVE_PORT, htobe16(v->dest_port));
     133           0 :                 if (r < 0)
     134           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_PORT attribute: %m");
     135             :         }
     136             : 
     137           0 :         if (v->flow_label > 0) {
     138           0 :                 r = sd_netlink_message_append_u32(m, IFLA_GENEVE_LABEL, htobe32(v->flow_label));
     139           0 :                 if (r < 0)
     140           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_LABEL attribute: %m");
     141             :         }
     142             : 
     143           0 :         if (v->geneve_df != _NETDEV_GENEVE_DF_INVALID) {
     144           0 :                 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_DF, v->geneve_df);
     145           0 :                 if (r < 0)
     146           0 :                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_DF attribute: %m");
     147             :         }
     148             : 
     149           0 :         r = sd_netlink_message_close_container(m);
     150           0 :         if (r < 0)
     151           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
     152             : 
     153           0 :         r = sd_netlink_message_close_container(m);
     154           0 :         if (r < 0)
     155           0 :                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
     156             : 
     157           0 :         r = netlink_call_async(netdev->manager->rtnl, NULL, m, geneve_netdev_create_handler,
     158             :                                netdev_destroy_callback, netdev);
     159           0 :         if (r < 0)
     160           0 :                 return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
     161             : 
     162           0 :         netdev_ref(netdev);
     163           0 :         netdev->state = NETDEV_STATE_CREATING;
     164             : 
     165           0 :         log_netdev_debug(netdev, "Creating");
     166             : 
     167           0 :         return r;
     168             : }
     169             : 
     170           0 : int config_parse_geneve_vni(const char *unit,
     171             :                            const char *filename,
     172             :                            unsigned line,
     173             :                            const char *section,
     174             :                            unsigned section_line,
     175             :                            const char *lvalue,
     176             :                            int ltype,
     177             :                            const char *rvalue,
     178             :                            void *data,
     179             :                            void *userdata) {
     180           0 :         Geneve *v = userdata;
     181             :         uint32_t f;
     182             :         int r;
     183             : 
     184           0 :         assert(filename);
     185           0 :         assert(lvalue);
     186           0 :         assert(rvalue);
     187           0 :         assert(data);
     188             : 
     189           0 :         r = safe_atou32(rvalue, &f);
     190           0 :         if (r < 0) {
     191           0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve VNI '%s'.", rvalue);
     192           0 :                 return 0;
     193             :         }
     194             : 
     195           0 :         if (f > GENEVE_VID_MAX){
     196           0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Geneve VNI out is of range '%s'.", rvalue);
     197           0 :                 return 0;
     198             :         }
     199             : 
     200           0 :         v->id = f;
     201             : 
     202           0 :         return 0;
     203             : }
     204             : 
     205           0 : int config_parse_geneve_address(const char *unit,
     206             :                                 const char *filename,
     207             :                                 unsigned line,
     208             :                                 const char *section,
     209             :                                 unsigned section_line,
     210             :                                 const char *lvalue,
     211             :                                 int ltype,
     212             :                                 const char *rvalue,
     213             :                                 void *data,
     214             :                                 void *userdata) {
     215           0 :         Geneve *v = userdata;
     216           0 :         union in_addr_union *addr = data, buffer;
     217             :         int r, f;
     218             : 
     219           0 :         assert(filename);
     220           0 :         assert(lvalue);
     221           0 :         assert(rvalue);
     222           0 :         assert(data);
     223             : 
     224           0 :         r = in_addr_from_string_auto(rvalue, &f, &buffer);
     225           0 :         if (r < 0) {
     226           0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "geneve '%s' address is invalid, ignoring assignment: %s", lvalue, rvalue);
     227           0 :                 return 0;
     228             :         }
     229             : 
     230           0 :         r = in_addr_is_multicast(f, &buffer);
     231           0 :         if (r > 0) {
     232           0 :                 log_syntax(unit, LOG_ERR, filename, line, 0, "geneve invalid multicast '%s' address, ignoring assignment: %s", lvalue, rvalue);
     233           0 :                 return 0;
     234             :         }
     235             : 
     236           0 :         v->remote_family = f;
     237           0 :         *addr = buffer;
     238             : 
     239           0 :         return 0;
     240             : }
     241             : 
     242           0 : int config_parse_geneve_flow_label(const char *unit,
     243             :                                    const char *filename,
     244             :                                    unsigned line,
     245             :                                    const char *section,
     246             :                                    unsigned section_line,
     247             :                                    const char *lvalue,
     248             :                                    int ltype,
     249             :                                    const char *rvalue,
     250             :                                    void *data,
     251             :                                    void *userdata) {
     252           0 :         Geneve *v = userdata;
     253             :         uint32_t f;
     254             :         int r;
     255             : 
     256           0 :         assert(filename);
     257           0 :         assert(lvalue);
     258           0 :         assert(rvalue);
     259           0 :         assert(data);
     260             : 
     261           0 :         r = safe_atou32(rvalue, &f);
     262           0 :         if (r < 0) {
     263           0 :                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Geneve flow label '%s'.", rvalue);
     264           0 :                 return 0;
     265             :         }
     266             : 
     267           0 :         if (f & ~GENEVE_FLOW_LABEL_MAX_MASK) {
     268           0 :                 log_syntax(unit, LOG_ERR, filename, line, r,
     269             :                            "Geneve flow label '%s' not valid. Flow label range should be [0-1048575].", rvalue);
     270           0 :                 return 0;
     271             :         }
     272             : 
     273           0 :         v->flow_label = f;
     274             : 
     275           0 :         return 0;
     276             : }
     277             : 
     278           0 : int config_parse_geneve_ttl(const char *unit,
     279             :                             const char *filename,
     280             :                             unsigned line,
     281             :                             const char *section,
     282             :                             unsigned section_line,
     283             :                             const char *lvalue,
     284             :                             int ltype,
     285             :                             const char *rvalue,
     286             :                             void *data,
     287             :                             void *userdata) {
     288           0 :         Geneve *v = userdata;
     289             :         unsigned f;
     290             :         int r;
     291             : 
     292           0 :         assert(filename);
     293           0 :         assert(lvalue);
     294           0 :         assert(rvalue);
     295           0 :         assert(data);
     296             : 
     297           0 :         if (streq(rvalue, "inherit"))
     298           0 :                 v->inherit = true;
     299             :         else {
     300           0 :                 r = safe_atou(rvalue, &f);
     301           0 :                 if (r < 0) {
     302           0 :                         log_syntax(unit, LOG_ERR, filename, line, r,
     303             :                                    "Failed to parse Geneve TTL '%s', ignoring assignment: %m", rvalue);
     304           0 :                         return 0;
     305             :                 }
     306             : 
     307           0 :                 if (f > 255) {
     308           0 :                         log_syntax(unit, LOG_ERR, filename, line, 0,
     309             :                                    "Invalid Geneve TTL '%s'. TTL must be <= 255. Ignoring assignment.", rvalue);
     310           0 :                         return 0;
     311             :                 }
     312             : 
     313           0 :                 v->ttl = f;
     314             :         }
     315             : 
     316           0 :         return 0;
     317             : }
     318             : 
     319           0 : static int netdev_geneve_verify(NetDev *netdev, const char *filename) {
     320           0 :         Geneve *v = GENEVE(netdev);
     321             : 
     322           0 :         assert(netdev);
     323           0 :         assert(v);
     324           0 :         assert(filename);
     325             : 
     326           0 :         if (v->id > GENEVE_VID_MAX)
     327           0 :                 return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
     328             :                                                 "%s: Geneve without valid VNI (or Virtual Network Identifier) configured. Ignoring.",
     329             :                                                 filename);
     330             : 
     331           0 :         return 0;
     332             : }
     333             : 
     334           0 : static void geneve_init(NetDev *netdev) {
     335             :         Geneve *v;
     336             : 
     337           0 :         assert(netdev);
     338             : 
     339           0 :         v = GENEVE(netdev);
     340             : 
     341           0 :         assert(v);
     342             : 
     343           0 :         v->id = GENEVE_VID_MAX + 1;
     344           0 :         v->geneve_df = _NETDEV_GENEVE_DF_INVALID;
     345           0 :         v->dest_port = DEFAULT_GENEVE_DESTINATION_PORT;
     346           0 :         v->udpcsum = false;
     347           0 :         v->udp6zerocsumtx = false;
     348           0 :         v->udp6zerocsumrx = false;
     349           0 : }
     350             : 
     351             : const NetDevVTable geneve_vtable = {
     352             :         .object_size = sizeof(Geneve),
     353             :         .init = geneve_init,
     354             :         .sections = "Match\0NetDev\0GENEVE\0",
     355             :         .create = netdev_geneve_create,
     356             :         .create_type = NETDEV_CREATE_INDEPENDENT,
     357             :         .config_verify = netdev_geneve_verify,
     358             :         .generate_mac = true,
     359             : };

Generated by: LCOV version 1.14