1 /* 2 * Copyright (c) 2015 FUJITSU LIMITED 3 * Author: Yang Hongyang <yanghy@cn.fujitsu.com> 4 * 5 * This work is licensed under the terms of the GNU GPL, version 2 or 6 * later. See the COPYING file in the top-level directory. 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qapi/error.h" 11 #include "qapi/qmp/qerror.h" 12 #include "qemu/error-report.h" 13 14 #include "net/filter.h" 15 #include "net/net.h" 16 #include "net/vhost_net.h" 17 #include "qom/object_interfaces.h" 18 #include "qemu/iov.h" 19 #include "qemu/module.h" 20 #include "net/colo.h" 21 #include "migration/colo.h" 22 23 static inline bool qemu_can_skip_netfilter(NetFilterState *nf) 24 { 25 return !nf->on; 26 } 27 28 ssize_t qemu_netfilter_receive(NetFilterState *nf, 29 NetFilterDirection direction, 30 NetClientState *sender, 31 unsigned flags, 32 const struct iovec *iov, 33 int iovcnt, 34 NetPacketSent *sent_cb) 35 { 36 if (qemu_can_skip_netfilter(nf)) { 37 return 0; 38 } 39 if (nf->direction == direction || 40 nf->direction == NET_FILTER_DIRECTION_ALL) { 41 return NETFILTER_GET_CLASS(OBJECT(nf))->receive_iov( 42 nf, sender, flags, iov, iovcnt, sent_cb); 43 } 44 45 return 0; 46 } 47 48 static NetFilterState *netfilter_next(NetFilterState *nf, 49 NetFilterDirection dir) 50 { 51 NetFilterState *next; 52 53 if (dir == NET_FILTER_DIRECTION_TX) { 54 /* forward walk through filters */ 55 next = QTAILQ_NEXT(nf, next); 56 } else { 57 /* reverse order */ 58 next = QTAILQ_PREV(nf, next); 59 } 60 61 return next; 62 } 63 64 ssize_t qemu_netfilter_pass_to_next(NetClientState *sender, 65 unsigned flags, 66 const struct iovec *iov, 67 int iovcnt, 68 void *opaque) 69 { 70 int ret = 0; 71 int direction; 72 NetFilterState *nf = opaque; 73 NetFilterState *next = NULL; 74 75 if (!sender || !sender->peer) { 76 /* no receiver, or sender been deleted, no need to pass it further */ 77 goto out; 78 } 79 80 if (nf->direction == NET_FILTER_DIRECTION_ALL) { 81 if (sender == nf->netdev) { 82 /* This packet is sent by netdev itself */ 83 direction = NET_FILTER_DIRECTION_TX; 84 } else { 85 direction = NET_FILTER_DIRECTION_RX; 86 } 87 } else { 88 direction = nf->direction; 89 } 90 91 next = netfilter_next(nf, direction); 92 while (next) { 93 /* 94 * if qemu_netfilter_pass_to_next been called, means that 95 * the packet has been hold by filter and has already retured size 96 * to the sender, so sent_cb shouldn't be called later, just 97 * pass NULL to next. 98 */ 99 ret = qemu_netfilter_receive(next, direction, sender, flags, iov, 100 iovcnt, NULL); 101 if (ret) { 102 return ret; 103 } 104 next = netfilter_next(next, direction); 105 } 106 107 /* 108 * We have gone through all filters, pass it to receiver. 109 * Do the valid check again incase sender or receiver been 110 * deleted while we go through filters. 111 */ 112 if (sender && sender->peer) { 113 qemu_net_queue_send_iov(sender->peer->incoming_queue, 114 sender, flags, iov, iovcnt, NULL); 115 } 116 117 out: 118 /* no receiver, or sender been deleted */ 119 return iov_size(iov, iovcnt); 120 } 121 122 static char *netfilter_get_netdev_id(Object *obj, Error **errp) 123 { 124 NetFilterState *nf = NETFILTER(obj); 125 126 return g_strdup(nf->netdev_id); 127 } 128 129 static void netfilter_set_netdev_id(Object *obj, const char *str, Error **errp) 130 { 131 NetFilterState *nf = NETFILTER(obj); 132 133 nf->netdev_id = g_strdup(str); 134 } 135 136 static int netfilter_get_direction(Object *obj, Error **errp G_GNUC_UNUSED) 137 { 138 NetFilterState *nf = NETFILTER(obj); 139 return nf->direction; 140 } 141 142 static void netfilter_set_direction(Object *obj, int direction, Error **errp) 143 { 144 NetFilterState *nf = NETFILTER(obj); 145 nf->direction = direction; 146 } 147 148 static char *netfilter_get_status(Object *obj, Error **errp) 149 { 150 NetFilterState *nf = NETFILTER(obj); 151 152 return nf->on ? g_strdup("on") : g_strdup("off"); 153 } 154 155 static void netfilter_set_status(Object *obj, const char *str, Error **errp) 156 { 157 NetFilterState *nf = NETFILTER(obj); 158 NetFilterClass *nfc = NETFILTER_GET_CLASS(obj); 159 160 if (strcmp(str, "on") && strcmp(str, "off")) { 161 error_setg(errp, "Invalid value for netfilter status, " 162 "should be 'on' or 'off'"); 163 return; 164 } 165 if (nf->on == !strcmp(str, "on")) { 166 return; 167 } 168 nf->on = !nf->on; 169 if (nf->netdev && nfc->status_changed) { 170 nfc->status_changed(nf, errp); 171 } 172 } 173 174 static void netfilter_init(Object *obj) 175 { 176 NetFilterState *nf = NETFILTER(obj); 177 178 nf->on = true; 179 180 object_property_add_str(obj, "netdev", 181 netfilter_get_netdev_id, netfilter_set_netdev_id, 182 NULL); 183 object_property_add_enum(obj, "queue", "NetFilterDirection", 184 &NetFilterDirection_lookup, 185 netfilter_get_direction, netfilter_set_direction, 186 NULL); 187 object_property_add_str(obj, "status", 188 netfilter_get_status, netfilter_set_status, 189 NULL); 190 } 191 192 static void netfilter_complete(UserCreatable *uc, Error **errp) 193 { 194 NetFilterState *nf = NETFILTER(uc); 195 NetClientState *ncs[MAX_QUEUE_NUM]; 196 NetFilterClass *nfc = NETFILTER_GET_CLASS(uc); 197 int queues; 198 Error *local_err = NULL; 199 200 if (!nf->netdev_id) { 201 error_setg(errp, "Parameter 'netdev' is required"); 202 return; 203 } 204 205 queues = qemu_find_net_clients_except(nf->netdev_id, ncs, 206 NET_CLIENT_DRIVER_NIC, 207 MAX_QUEUE_NUM); 208 if (queues < 1) { 209 error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev", 210 "a network backend id"); 211 return; 212 } else if (queues > 1) { 213 error_setg(errp, "multiqueue is not supported"); 214 return; 215 } 216 217 if (get_vhost_net(ncs[0])) { 218 error_setg(errp, "Vhost is not supported"); 219 return; 220 } 221 222 nf->netdev = ncs[0]; 223 224 if (nfc->setup) { 225 nfc->setup(nf, &local_err); 226 if (local_err) { 227 error_propagate(errp, local_err); 228 return; 229 } 230 } 231 QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next); 232 } 233 234 static void netfilter_finalize(Object *obj) 235 { 236 NetFilterState *nf = NETFILTER(obj); 237 NetFilterClass *nfc = NETFILTER_GET_CLASS(obj); 238 239 if (nfc->cleanup) { 240 nfc->cleanup(nf); 241 } 242 243 if (nf->netdev && !QTAILQ_EMPTY(&nf->netdev->filters) && 244 QTAILQ_IN_USE(nf, next)) { 245 QTAILQ_REMOVE(&nf->netdev->filters, nf, next); 246 } 247 g_free(nf->netdev_id); 248 } 249 250 static void default_handle_event(NetFilterState *nf, int event, Error **errp) 251 { 252 switch (event) { 253 case COLO_EVENT_CHECKPOINT: 254 break; 255 case COLO_EVENT_FAILOVER: 256 object_property_set_str(OBJECT(nf), "off", "status", errp); 257 break; 258 default: 259 break; 260 } 261 } 262 263 static void netfilter_class_init(ObjectClass *oc, void *data) 264 { 265 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); 266 NetFilterClass *nfc = NETFILTER_CLASS(oc); 267 268 ucc->complete = netfilter_complete; 269 nfc->handle_event = default_handle_event; 270 } 271 272 static const TypeInfo netfilter_info = { 273 .name = TYPE_NETFILTER, 274 .parent = TYPE_OBJECT, 275 .abstract = true, 276 .class_size = sizeof(NetFilterClass), 277 .class_init = netfilter_class_init, 278 .instance_size = sizeof(NetFilterState), 279 .instance_init = netfilter_init, 280 .instance_finalize = netfilter_finalize, 281 .interfaces = (InterfaceInfo[]) { 282 { TYPE_USER_CREATABLE }, 283 { } 284 } 285 }; 286 287 static void register_types(void) 288 { 289 type_register_static(&netfilter_info); 290 } 291 292 type_init(register_types); 293