1 /* SPDX-License-Identifier: LGPL-2.1-or-later
2  * Copyright © 2020 VMware, Inc. */
3 
4 #include "networkd-link.h"
5 #include "networkd-manager.h"
6 #include "networkd-queue.h"
7 #include "networkd-sriov.h"
8 
sr_iov_handler(sd_netlink * rtnl,sd_netlink_message * m,Request * req,Link * link,SRIOV * sr_iov)9 static int sr_iov_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, SRIOV *sr_iov) {
10         int r;
11 
12         assert(m);
13         assert(link);
14 
15         r = sd_netlink_message_get_errno(m);
16         if (r < 0 && r != -EEXIST) {
17                 log_link_message_error_errno(link, m, r, "Could not set up SR-IOV");
18                 link_enter_failed(link);
19                 return 1;
20         }
21 
22         if (link->sr_iov_messages == 0) {
23                 log_link_debug(link, "SR-IOV configured");
24                 link->sr_iov_configured = true;
25                 link_check_ready(link);
26         }
27 
28         return 1;
29 }
30 
sr_iov_configure(SRIOV * sr_iov,Link * link,Request * req)31 static int sr_iov_configure(SRIOV *sr_iov, Link *link, Request *req) {
32         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
33         int r;
34 
35         assert(sr_iov);
36         assert(link);
37         assert(link->manager);
38         assert(link->manager->rtnl);
39         assert(link->ifindex > 0);
40         assert(req);
41 
42         log_link_debug(link, "Setting SR-IOV virtual function %"PRIu32".", sr_iov->vf);
43 
44         r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
45         if (r < 0)
46                 return r;
47 
48         r = sr_iov_set_netlink_message(sr_iov, m);
49         if (r < 0)
50                 return r;
51 
52         return request_call_netlink_async(link->manager->rtnl, m, req);
53 }
54 
sr_iov_process_request(Request * req,Link * link,SRIOV * sr_iov)55 static int sr_iov_process_request(Request *req, Link *link, SRIOV *sr_iov) {
56         int r;
57 
58         assert(req);
59         assert(link);
60         assert(sr_iov);
61 
62         if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
63                 return 0;
64 
65         r = sr_iov_configure(sr_iov, link, req);
66         if (r < 0)
67                 return log_link_warning_errno(link, r,
68                                               "Failed to configure SR-IOV virtual function %"PRIu32": %m",
69                                               sr_iov->vf);
70 
71         return 1;
72 }
73 
link_request_sr_iov_vfs(Link * link)74 int link_request_sr_iov_vfs(Link *link) {
75         SRIOV *sr_iov;
76         int r;
77 
78         assert(link);
79         assert(link->network);
80 
81         link->sr_iov_configured = false;
82 
83         ORDERED_HASHMAP_FOREACH(sr_iov, link->network->sr_iov_by_section) {
84                 r = link_queue_request_safe(link, REQUEST_TYPE_SRIOV,
85                                             sr_iov, NULL,
86                                             sr_iov_hash_func,
87                                             sr_iov_compare_func,
88                                             sr_iov_process_request,
89                                             &link->sr_iov_messages,
90                                             sr_iov_handler,
91                                             NULL);
92                 if (r < 0)
93                         return log_link_warning_errno(link, r,
94                                                       "Failed to request SR-IOV virtual function %"PRIu32": %m",
95                                                       sr_iov->vf);
96         }
97 
98         if (link->sr_iov_messages == 0) {
99                 link->sr_iov_configured = true;
100                 link_check_ready(link);
101         } else
102                 log_link_debug(link, "Configuring SR-IOV");
103 
104         return 0;
105 }
106