static int run_test(void) { struct { struct kdbus_cmd_make head; /* bloom size item */ struct { uint64_t size; uint64_t type; struct kdbus_bloom_parameter bloom; } bs; /* name item */ uint64_t n_size; uint64_t n_type; char name[64]; } bus_make; char *bus; struct conn *conn_a, *conn_b; uint64_t cookie; int fdc; int ret; printf("-- opening /dev/" KBUILD_MODNAME "/control\n"); fdc = open("/dev/" KBUILD_MODNAME "/control", O_RDWR|O_CLOEXEC); if (fdc < 0) { fprintf(stderr, "--- error %d (%m)\n", fdc); return EXIT_FAILURE; } memset(&bus_make, 0, sizeof(bus_make)); bus_make.head.flags = KDBUS_MAKE_POLICY_OPEN; bus_make.bs.size = sizeof(bus_make.bs); bus_make.bs.type = KDBUS_ITEM_BLOOM_PARAMETER; bus_make.bs.bloom.size = 64; bus_make.bs.bloom.n_hash = 1; snprintf(bus_make.name, sizeof(bus_make.name), "%u-testbus", getuid()); bus_make.n_type = KDBUS_ITEM_MAKE_NAME; bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; bus_make.head.size = sizeof(struct kdbus_cmd_make) + sizeof(bus_make.bs) + bus_make.n_size; printf("-- creating bus '%s'\n", bus_make.name); ret = ioctl(fdc, KDBUS_CMD_BUS_MAKE, &bus_make); if (ret) { fprintf(stderr, "--- error %d (%m)\n", ret); return EXIT_FAILURE; } if (asprintf(&bus, "/dev/" KBUILD_MODNAME "/%s/bus", bus_make.name) < 0) return EXIT_FAILURE; conn_a = connect_to_bus(bus, 0); conn_b = connect_to_bus(bus, 0); if (!conn_a || !conn_b) return EXIT_FAILURE; cookie = 0; msg_send(conn_b, NULL, ++cookie, 0, 0, 25, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, -600, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, 10, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, -35, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, -100, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, 20, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, -15, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, -800, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, -150, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, -150, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, 10, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, -800, conn_a->id); msg_send(conn_b, NULL, ++cookie, 0, 0, -10, conn_a->id); printf("--- get priority -200\n"); for (;;) { if (msg_recv_prio(conn_a, -200) < 0) break; } printf("--- get priority -100\n"); for (;;) { if (msg_recv_prio(conn_a, -100) < 0) break; } printf("--- get priority 10\n"); for (;;) { if (msg_recv_prio(conn_a, 10) < 0) break; } printf("--- get priority (all)\n"); for (;;) { if (msg_recv(conn_a) < 0) break; } close(conn_a->fd); close(conn_b->fd); free(conn_a); free(conn_b); close(fdc); free(bus); return EXIT_SUCCESS; }
static int msg_recv_prio(struct kdbus_conn *conn, int64_t requested_prio, int64_t expected_prio) { struct kdbus_cmd_recv recv = { .size = sizeof(recv), .flags = KDBUS_RECV_USE_PRIORITY, .priority = requested_prio, }; struct kdbus_msg *msg; int ret; ret = ioctl(conn->fd, KDBUS_CMD_RECV, &recv); if (ret < 0) { kdbus_printf("error receiving message: %d (%m)\n", -errno); return -errno; } msg = (struct kdbus_msg *)(conn->buf + recv.reply.offset); kdbus_msg_dump(conn, msg); if (msg->priority != expected_prio) { kdbus_printf("expected message prio %lld, got %lld\n", (unsigned long long) expected_prio, (unsigned long long) msg->priority); return -EINVAL; } kdbus_msg_free(msg); ret = kdbus_free(conn, recv.reply.offset); if (ret < 0) return ret; return 0; } int kdbus_test_message_prio(struct kdbus_test_env *env) { struct kdbus_conn *a, *b; uint64_t cookie = 0; a = kdbus_hello(env->buspath, 0, NULL, 0); b = kdbus_hello(env->buspath, 0, NULL, 0); ASSERT_RETURN(a && b); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 25, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -600, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -35, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -100, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 20, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -15, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -150, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0); ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -10, a->id) == 0); ASSERT_RETURN(msg_recv_prio(a, -200, -800) == 0); ASSERT_RETURN(msg_recv_prio(a, -100, -800) == 0); ASSERT_RETURN(msg_recv_prio(a, -400, -600) == 0); ASSERT_RETURN(msg_recv_prio(a, -400, -600) == -ENOMSG); ASSERT_RETURN(msg_recv_prio(a, 10, -150) == 0); ASSERT_RETURN(msg_recv_prio(a, 10, -100) == 0); kdbus_printf("--- get priority (all)\n"); ASSERT_RETURN(kdbus_msg_recv(a, NULL, NULL) == 0); kdbus_conn_free(a); kdbus_conn_free(b); return TEST_OK; } static int kdbus_test_notify_kernel_quota(struct kdbus_test_env *env) { int ret; unsigned int i; uint64_t offset; struct kdbus_conn *conn; struct kdbus_conn *reader; struct kdbus_msg *msg = NULL; reader = kdbus_hello(env->buspath, 0, NULL, 0); ASSERT_RETURN(reader); conn = kdbus_hello(env->buspath, 0, NULL, 0); ASSERT_RETURN(conn); /* Register for ID signals */ ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD, KDBUS_MATCH_ID_ANY); ASSERT_RETURN(ret == 0); ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE, KDBUS_MATCH_ID_ANY); ASSERT_RETURN(ret == 0); /* Each iteration two notifications: add and remove ID */ for (i = 0; i < KDBUS_CONN_MAX_MSGS / 2; i++) { struct kdbus_conn *notifier; notifier = kdbus_hello(env->buspath, 0, NULL, 0); ASSERT_RETURN(notifier); kdbus_conn_free(notifier); } /* * Now the reader queue is full, message will be lost * but it will not be accounted in dropped msgs */ ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, reader->id); ASSERT_RETURN(ret == -ENOBUFS); /* More ID kernel notifications that will be lost */ kdbus_conn_free(conn); conn = kdbus_hello(env->buspath, 0, NULL, 0); ASSERT_RETURN(conn); kdbus_conn_free(conn); ret = kdbus_msg_recv(reader, &msg, &offset); ASSERT_RETURN(ret == -EOVERFLOW); /* * We lost only 3 packet since only broadcast mesg * are accounted. The connection ID add/remove notification */ ASSERT_RETURN(offset == 3); kdbus_msg_free(msg); /* Read our queue */ for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) { ret = kdbus_msg_recv_poll(reader, 100, &msg, NULL); ASSERT_RETURN(ret == 0); kdbus_msg_free(msg); } ret = kdbus_msg_recv(reader, NULL, NULL); ASSERT_RETURN(ret == -EAGAIN); kdbus_conn_free(reader); return 0; }