summaryrefslogtreecommitdiffstats
path: root/src/network/networkd-queue.h
blob: 6db0005e619054521dae3d574833346ef69908c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once

#include "sd-event.h"
#include "sd-netlink.h"

#include "alloc-util.h"
#include "hash-funcs.h"

typedef struct Link Link;
typedef struct NetDev NetDev;
typedef struct Manager Manager;
typedef struct Request Request;

typedef int (*request_process_func_t)(Request *req, Link *link, void *userdata);
typedef int (*request_netlink_handler_t)(sd_netlink *nl, sd_netlink_message *m, Request *req, Link *link, void *userdata);

typedef enum RequestType {
        REQUEST_TYPE_ACTIVATE_LINK,
        REQUEST_TYPE_ADDRESS,
        REQUEST_TYPE_ADDRESS_LABEL,
        REQUEST_TYPE_BRIDGE_FDB,
        REQUEST_TYPE_BRIDGE_MDB,
        REQUEST_TYPE_DHCP_SERVER,
        REQUEST_TYPE_DHCP4_CLIENT,
        REQUEST_TYPE_DHCP6_CLIENT,
        REQUEST_TYPE_IPV6_PROXY_NDP,
        REQUEST_TYPE_NDISC,
        REQUEST_TYPE_NEIGHBOR,
        REQUEST_TYPE_NETDEV_INDEPENDENT,
        REQUEST_TYPE_NETDEV_STACKED,
        REQUEST_TYPE_NEXTHOP,
        REQUEST_TYPE_RADV,
        REQUEST_TYPE_ROUTE,
        REQUEST_TYPE_ROUTING_POLICY_RULE,
        REQUEST_TYPE_SET_LINK_ADDRESS_GENERATION_MODE, /* Setting IPv6LL address generation mode. */
        REQUEST_TYPE_SET_LINK_BOND,                    /* Setting bond configs. */
        REQUEST_TYPE_SET_LINK_BRIDGE,                  /* Setting bridge configs. */
        REQUEST_TYPE_SET_LINK_BRIDGE_VLAN,             /* Setting bridge VLAN configs. */
        REQUEST_TYPE_SET_LINK_CAN,                     /* Setting CAN interface configs. */
        REQUEST_TYPE_SET_LINK_FLAGS,                   /* Setting IFF_NOARP or friends. */
        REQUEST_TYPE_SET_LINK_GROUP,                   /* Setting interface group. */
        REQUEST_TYPE_SET_LINK_IPOIB,                   /* Setting IPoIB configs. */
        REQUEST_TYPE_SET_LINK_MAC,                     /* Setting MAC address. */
        REQUEST_TYPE_SET_LINK_MASTER,                  /* Setting IFLA_MASTER. */
        REQUEST_TYPE_SET_LINK_MTU,                     /* Setting MTU. */
        REQUEST_TYPE_SRIOV,
        REQUEST_TYPE_TC_CLASS,
        REQUEST_TYPE_TC_QDISC,
        REQUEST_TYPE_UP_DOWN,
        _REQUEST_TYPE_MAX,
        _REQUEST_TYPE_INVALID = -EINVAL,
} RequestType;

struct Request {
        unsigned n_ref;

        Manager *manager; /* must be non-NULL */
        Link *link; /* can be NULL */

        RequestType type;

        /* Target object, e.g. Address, Route, NetDev, and so on. */
        void *userdata;
        /* freeing userdata when the request is completed or failed. */
        mfree_func_t free_func;

        /* hash and compare functions for userdata, used for dedup requests. */
        hash_func_t hash_func;
        compare_func_t compare_func;

        /* Checks the request dependencies, and then processes this request, e.g. call address_configure().
         * Return 1 when processed, 0 when its dependencies not resolved, and negative errno on failure. */
        request_process_func_t process;

        /* incremented when requested, decremented when request is completed or failed. */
        unsigned *counter;
        /* called in netlink handler, the 'counter' is decremented before this is called.
         * If this is specified, then the 'process' function must increment the reference of this
         * request, and pass this request to the netlink_call_async(), and set the destroy function
         * to the slot. */
        request_netlink_handler_t netlink_handler;
};

Request *request_ref(Request *req);
Request *request_unref(Request *req);
DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_unref);

void request_detach(Manager *manager, Request *req);

int netdev_queue_request(
                NetDev *netdev,
                request_process_func_t process,
                Request **ret);

int link_queue_request_full(
                Link *link,
                RequestType type,
                void *userdata,
                mfree_func_t free_func,
                hash_func_t hash_func,
                compare_func_t compare_func,
                request_process_func_t process,
                unsigned *counter,
                request_netlink_handler_t netlink_handler,
                Request **ret);

static inline int link_queue_request(
                Link *link,
                RequestType type,
                request_process_func_t process,
                Request **ret) {

        return link_queue_request_full(link, type, NULL, NULL, NULL, NULL,
                                       process, NULL, NULL, ret);
}

#define link_queue_request_safe(link, type, userdata, free_func, hash_func, compare_func, process, counter, netlink_handler, ret) \
        ({                                                              \
                typeof(userdata) (*_f)(typeof(userdata)) = (free_func); \
                void (*_h)(const typeof(*userdata)*, struct siphash*) = (hash_func); \
                int (*_c)(const typeof(*userdata)*, const typeof(*userdata)*) = (compare_func); \
                int (*_p)(Request*, Link*, typeof(userdata)) = (process); \
                int (*_n)(sd_netlink*, sd_netlink_message*, Request*, Link*, typeof(userdata)) = (netlink_handler); \
                                                                        \
                link_queue_request_full(link, type, userdata,           \
                                        (mfree_func_t) _f,              \
                                        (hash_func_t) _h,               \
                                        (compare_func_t) _c,            \
                                        (request_process_func_t) _p,    \
                                        counter,                        \
                                        (request_netlink_handler_t) _n, \
                                        ret);                           \
        })

int manager_process_requests(sd_event_source *s, void *userdata);
int request_call_netlink_async(sd_netlink *nl, sd_netlink_message *m, Request *req);

const char* request_type_to_string(RequestType t) _const_;