forked from openSUSE/wicked
/
infiniband.c
136 lines (114 loc) · 3.27 KB
/
infiniband.c
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
/*
* infiniband handling
*
* Copyright (C) 2013 Marius Tomaschewski <mt@suse.de>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <wicked/infiniband.h>
#include <wicked/netinfo.h>
#include <wicked/util.h>
#include "util_priv.h"
/*
* Maps for ipoib connection mode and user-multicast option values
*/
static const ni_intmap_t __map_ipoib_mode[] = {
{ "datagram", NI_INFINIBAND_MODE_DATAGRAM },
{ "connected", NI_INFINIBAND_MODE_CONNECTED },
{ NULL, ~0 },
};
static const ni_intmap_t __map_ipoib_umcast[] = {
{ "disallowed", NI_INFINIBAND_UMCAST_DISALLOWED },
{ "allowed", NI_INFINIBAND_UMCAST_ALLOWED },
{ NULL, ~0 },
};
ni_infiniband_t *
ni_infiniband_new(void)
{
ni_infiniband_t *ib;
ib = xcalloc(1, sizeof(*ib));
/* Apply "not set" defaults */
ib->pkey = NI_INFINIBAND_DEFAULT_PKEY;
ib->mode = NI_INFINIBAND_VALUE_NOT_SET;
ib->umcast = NI_INFINIBAND_VALUE_NOT_SET;
return ib;
}
void
ni_infiniband_free(ni_infiniband_t *ib)
{
if (ib) {
free(ib);
}
}
const char *
ni_infiniband_get_mode_name(unsigned int mode)
{
return ni_format_uint_mapped(mode, __map_ipoib_mode);
}
ni_bool_t
ni_infiniband_get_mode_flag(const char *mode, unsigned int *fp)
{
unsigned int flag = NI_INFINIBAND_VALUE_NOT_SET;
if (!mode || !fp)
return FALSE;
if (ni_parse_uint_mapped(mode, __map_ipoib_mode, &flag) < 0)
return FALSE;
*fp = flag;
return TRUE;
}
const char *
ni_infiniband_get_umcast_name(unsigned int umcast)
{
return ni_format_uint_mapped(umcast, __map_ipoib_umcast);
}
ni_bool_t
ni_infiniband_get_umcast_flag(const char *umcast, unsigned int *fp)
{
unsigned int flag = NI_INFINIBAND_VALUE_NOT_SET;
if (!umcast || !fp)
return FALSE;
if (ni_parse_uint_maybe_mapped(umcast, __map_ipoib_umcast, &flag, 10) != 0)
return FALSE;
*fp = flag;
return TRUE;
}
const char *
ni_infiniband_validate(ni_iftype_t iftype, const ni_infiniband_t *ib,
const ni_netdev_ref_t *lowerdev)
{
switch (iftype) {
default:
return "Not a valid infiniband interface type";
case NI_IFTYPE_INFINIBAND:
if (!ib)
return "Invalid/empty infiniband configuration";
if (ib->pkey != NI_INFINIBAND_DEFAULT_PKEY)
return "Infiniband partition key supported for child interfaces only";
if (lowerdev && !ni_string_empty(lowerdev->name))
return "Infiniband parent supported for child interfaces only";
break;
case NI_IFTYPE_INFINIBAND_CHILD:
if (!ib)
return "Invalid/empty infiniband child configuration";
if (!lowerdev || ni_string_empty(lowerdev->name))
return "Infiniband parent device name required for child interfaces";
/*
* we currently use sysfs, that always ORs with 0x8000,
* new rtnetlink code does not seem to constrain it and
* the children inherit parent key as default (0xffff)
* so we may remove this when switching to rtnetlink.
*/
if (ib->pkey < 0x8000 || ib->pkey == NI_INFINIBAND_DEFAULT_PKEY)
return "Infiniband partition key not in supported range (0x8000..0xffff)";
break;
}
if (ib->mode != NI_INFINIBAND_VALUE_NOT_SET &&
ni_infiniband_get_mode_name(ib->mode) == NULL)
return "Invalid/unsupported infiniband connection-mode";
if (ib->umcast != NI_INFINIBAND_VALUE_NOT_SET &&
ni_infiniband_get_umcast_name(ib->umcast) == NULL)
return "Invalid/unsupported infiniband user-multicast policy";
return NULL;
}