aboutsummaryrefslogtreecommitdiff
path: root/linux-user/fd-trans.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/fd-trans.c')
-rw-r--r--linux-user/fd-trans.c263
1 files changed, 256 insertions, 7 deletions
diff --git a/linux-user/fd-trans.c b/linux-user/fd-trans.c
index 6941089959..c04a97c73a 100644
--- a/linux-user/fd-trans.c
+++ b/linux-user/fd-trans.c
@@ -138,6 +138,9 @@ enum {
QEMU_IFLA_PROP_LIST,
QEMU_IFLA_ALT_IFNAME,
QEMU_IFLA_PERM_ADDRESS,
+ QEMU_IFLA_PROTO_DOWN_REASON,
+ QEMU_IFLA_PARENT_DEV_NAME,
+ QEMU_IFLA_PARENT_DEV_BUS_NAME,
QEMU___IFLA_MAX
};
@@ -179,6 +182,8 @@ enum {
QEMU_IFLA_BRPORT_BACKUP_PORT,
QEMU_IFLA_BRPORT_MRP_RING_OPEN,
QEMU_IFLA_BRPORT_MRP_IN_OPEN,
+ QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
+ QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
QEMU___IFLA_BRPORT_MAX
};
@@ -268,6 +273,37 @@ enum {
QEMU___RTA_MAX
};
+enum {
+ QEMU_IFLA_VF_STATS_RX_PACKETS,
+ QEMU_IFLA_VF_STATS_TX_PACKETS,
+ QEMU_IFLA_VF_STATS_RX_BYTES,
+ QEMU_IFLA_VF_STATS_TX_BYTES,
+ QEMU_IFLA_VF_STATS_BROADCAST,
+ QEMU_IFLA_VF_STATS_MULTICAST,
+ QEMU_IFLA_VF_STATS_PAD,
+ QEMU_IFLA_VF_STATS_RX_DROPPED,
+ QEMU_IFLA_VF_STATS_TX_DROPPED,
+ QEMU__IFLA_VF_STATS_MAX,
+};
+
+enum {
+ QEMU_IFLA_VF_UNSPEC,
+ QEMU_IFLA_VF_MAC,
+ QEMU_IFLA_VF_VLAN,
+ QEMU_IFLA_VF_TX_RATE,
+ QEMU_IFLA_VF_SPOOFCHK,
+ QEMU_IFLA_VF_LINK_STATE,
+ QEMU_IFLA_VF_RATE,
+ QEMU_IFLA_VF_RSS_QUERY_EN,
+ QEMU_IFLA_VF_STATS,
+ QEMU_IFLA_VF_TRUST,
+ QEMU_IFLA_VF_IB_NODE_GUID,
+ QEMU_IFLA_VF_IB_PORT_GUID,
+ QEMU_IFLA_VF_VLAN_LIST,
+ QEMU_IFLA_VF_BROADCAST,
+ QEMU__IFLA_VF_MAX,
+};
+
TargetFdTrans **target_fd_trans;
QemuMutex target_fd_trans_lock;
unsigned int target_fd_max;
@@ -573,6 +609,8 @@ static abi_long host_to_target_slave_data_bridge_nlattr(struct nlattr *nlattr,
/* uin32_t */
case QEMU_IFLA_BRPORT_COST:
case QEMU_IFLA_BRPORT_BACKUP_PORT:
+ case QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT:
+ case QEMU_IFLA_BRPORT_MCAST_EHT_HOSTS_CNT:
u32 = NLA_DATA(nlattr);
*u32 = tswap32(*u32);
break;
@@ -805,6 +843,145 @@ static abi_long host_to_target_data_xdp_nlattr(struct nlattr *nlattr,
return 0;
}
+static abi_long host_to_target_data_vlan_list_nlattr(struct nlattr *nlattr,
+ void *context)
+{
+ struct ifla_vf_vlan_info *vlan_info;
+
+ switch (nlattr->nla_type) {
+ /* struct ifla_vf_vlan_info */
+ case IFLA_VF_VLAN_INFO:
+ vlan_info = NLA_DATA(nlattr);
+ vlan_info->vf = tswap32(vlan_info->vf);
+ vlan_info->vlan = tswap32(vlan_info->vlan);
+ vlan_info->qos = tswap32(vlan_info->qos);
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "Unknown host VLAN LIST type: %d\n",
+ nlattr->nla_type);
+ break;
+ }
+ return 0;
+}
+
+static abi_long host_to_target_data_vf_stats_nlattr(struct nlattr *nlattr,
+ void *context)
+{
+ uint64_t *u64;
+
+ switch (nlattr->nla_type) {
+ /* uint64_t */
+ case QEMU_IFLA_VF_STATS_RX_PACKETS:
+ case QEMU_IFLA_VF_STATS_TX_PACKETS:
+ case QEMU_IFLA_VF_STATS_RX_BYTES:
+ case QEMU_IFLA_VF_STATS_TX_BYTES:
+ case QEMU_IFLA_VF_STATS_BROADCAST:
+ case QEMU_IFLA_VF_STATS_MULTICAST:
+ case QEMU_IFLA_VF_STATS_PAD:
+ case QEMU_IFLA_VF_STATS_RX_DROPPED:
+ case QEMU_IFLA_VF_STATS_TX_DROPPED:
+ u64 = NLA_DATA(nlattr);
+ *u64 = tswap64(*u64);
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "Unknown host VF STATS type: %d\n",
+ nlattr->nla_type);
+ break;
+ }
+ return 0;
+}
+
+static abi_long host_to_target_data_vfinfo_nlattr(struct nlattr *nlattr,
+ void *context)
+{
+ struct ifla_vf_mac *mac;
+ struct ifla_vf_vlan *vlan;
+ struct ifla_vf_vlan_info *vlan_info;
+ struct ifla_vf_spoofchk *spoofchk;
+ struct ifla_vf_rate *rate;
+ struct ifla_vf_link_state *link_state;
+ struct ifla_vf_rss_query_en *rss_query_en;
+ struct ifla_vf_trust *trust;
+ struct ifla_vf_guid *guid;
+
+ switch (nlattr->nla_type) {
+ /* struct ifla_vf_mac */
+ case QEMU_IFLA_VF_MAC:
+ mac = NLA_DATA(nlattr);
+ mac->vf = tswap32(mac->vf);
+ break;
+ /* struct ifla_vf_broadcast */
+ case QEMU_IFLA_VF_BROADCAST:
+ break;
+ /* struct struct ifla_vf_vlan */
+ case QEMU_IFLA_VF_VLAN:
+ vlan = NLA_DATA(nlattr);
+ vlan->vf = tswap32(vlan->vf);
+ vlan->vlan = tswap32(vlan->vlan);
+ vlan->qos = tswap32(vlan->qos);
+ break;
+ /* struct ifla_vf_vlan_info */
+ case QEMU_IFLA_VF_TX_RATE:
+ vlan_info = NLA_DATA(nlattr);
+ vlan_info->vf = tswap32(vlan_info->vf);
+ vlan_info->vlan = tswap32(vlan_info->vlan);
+ vlan_info->qos = tswap32(vlan_info->qos);
+ break;
+ /* struct ifla_vf_spoofchk */
+ case QEMU_IFLA_VF_SPOOFCHK:
+ spoofchk = NLA_DATA(nlattr);
+ spoofchk->vf = tswap32(spoofchk->vf);
+ spoofchk->setting = tswap32(spoofchk->setting);
+ break;
+ /* struct ifla_vf_rate */
+ case QEMU_IFLA_VF_RATE:
+ rate = NLA_DATA(nlattr);
+ rate->vf = tswap32(rate->vf);
+ rate->min_tx_rate = tswap32(rate->min_tx_rate);
+ rate->max_tx_rate = tswap32(rate->max_tx_rate);
+ break;
+ /* struct ifla_vf_link_state */
+ case QEMU_IFLA_VF_LINK_STATE:
+ link_state = NLA_DATA(nlattr);
+ link_state->vf = tswap32(link_state->vf);
+ link_state->link_state = tswap32(link_state->link_state);
+ break;
+ /* struct ifla_vf_rss_query_en */
+ case QEMU_IFLA_VF_RSS_QUERY_EN:
+ rss_query_en = NLA_DATA(nlattr);
+ rss_query_en->vf = tswap32(rss_query_en->vf);
+ rss_query_en->setting = tswap32(rss_query_en->setting);
+ break;
+ /* struct ifla_vf_trust */
+ case QEMU_IFLA_VF_TRUST:
+ trust = NLA_DATA(nlattr);
+ trust->vf = tswap32(trust->vf);
+ trust->setting = tswap32(trust->setting);
+ break;
+ /* struct ifla_vf_guid */
+ case QEMU_IFLA_VF_IB_NODE_GUID:
+ case QEMU_IFLA_VF_IB_PORT_GUID:
+ guid = NLA_DATA(nlattr);
+ guid->vf = tswap32(guid->vf);
+ guid->guid = tswap32(guid->guid);
+ break;
+ /* nested */
+ case QEMU_IFLA_VF_VLAN_LIST:
+ return host_to_target_for_each_nlattr(RTA_DATA(nlattr), nlattr->nla_len,
+ NULL,
+ host_to_target_data_vlan_list_nlattr);
+ case QEMU_IFLA_VF_STATS:
+ return host_to_target_for_each_nlattr(RTA_DATA(nlattr), nlattr->nla_len,
+ NULL,
+ host_to_target_data_vf_stats_nlattr);
+ default:
+ qemu_log_mask(LOG_UNIMP, "Unknown host VFINFO type: %d\n",
+ nlattr->nla_type);
+ break;
+ }
+ return 0;
+}
+
static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
{
uint32_t *u32;
@@ -818,9 +995,12 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
case QEMU_IFLA_ADDRESS:
case QEMU_IFLA_BROADCAST:
case QEMU_IFLA_PERM_ADDRESS:
+ case QEMU_IFLA_PHYS_PORT_ID:
/* string */
case QEMU_IFLA_IFNAME:
case QEMU_IFLA_QDISC:
+ case QEMU_IFLA_PARENT_DEV_NAME:
+ case QEMU_IFLA_PARENT_DEV_BUS_NAME:
break;
/* uin8_t */
case QEMU_IFLA_OPERSTATE:
@@ -939,6 +1119,10 @@ static abi_long host_to_target_data_link_rtattr(struct rtattr *rtattr)
return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
NULL,
host_to_target_data_xdp_nlattr);
+ case QEMU_IFLA_VFINFO_LIST:
+ return host_to_target_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
+ NULL,
+ host_to_target_data_vfinfo_nlattr);
default:
qemu_log_mask(LOG_UNIMP, "Unknown host QEMU_IFLA type: %d\n",
rtattr->rta_type);
@@ -1100,6 +1284,49 @@ static inline abi_long host_to_target_nlmsg_route(struct nlmsghdr *nlh,
return host_to_target_for_each_nlmsg(nlh, len, host_to_target_data_route);
}
+static abi_long target_to_host_for_each_nlattr(struct nlattr *nlattr,
+ size_t len,
+ abi_long (*target_to_host_nlattr)
+ (struct nlattr *))
+{
+ unsigned short aligned_nla_len;
+ abi_long ret;
+
+ while (len > sizeof(struct nlattr)) {
+ if (tswap16(nlattr->nla_len) < sizeof(struct rtattr) ||
+ tswap16(nlattr->nla_len) > len) {
+ break;
+ }
+ nlattr->nla_len = tswap16(nlattr->nla_len);
+ nlattr->nla_type = tswap16(nlattr->nla_type);
+ ret = target_to_host_nlattr(nlattr);
+ if (ret < 0) {
+ return ret;
+ }
+
+ aligned_nla_len = NLA_ALIGN(nlattr->nla_len);
+ if (aligned_nla_len >= len) {
+ break;
+ }
+ len -= aligned_nla_len;
+ nlattr = (struct nlattr *)(((char *)nlattr) + aligned_nla_len);
+ }
+ return 0;
+}
+
+static abi_long target_to_host_data_inet6_nlattr(struct nlattr *nlattr)
+{
+ switch (nlattr->nla_type) {
+ /* uint8_t */
+ case QEMU_IFLA_INET6_ADDR_GEN_MODE:
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "Unknown target AF_INET6 type: %d\n",
+ nlattr->nla_type);
+ }
+ return 0;
+}
+
static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr,
size_t len,
abi_long (*target_to_host_rtattr)
@@ -1130,16 +1357,35 @@ static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr,
return 0;
}
+static abi_long target_to_host_data_spec_nlattr(struct nlattr *nlattr)
+{
+ switch (nlattr->nla_type & NLA_TYPE_MASK) {
+ case AF_INET6:
+ return target_to_host_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len,
+ target_to_host_data_inet6_nlattr);
+ default:
+ qemu_log_mask(LOG_UNIMP, "Unknown target AF_SPEC type: %d\n",
+ nlattr->nla_type);
+ break;
+ }
+ return 0;
+}
+
static abi_long target_to_host_data_link_rtattr(struct rtattr *rtattr)
{
uint32_t *u32;
- switch (rtattr->rta_type) {
+ switch (rtattr->rta_type & NLA_TYPE_MASK) {
/* uint32_t */
+ case QEMU_IFLA_MTU:
+ case QEMU_IFLA_TXQLEN:
case QEMU_IFLA_EXT_MASK:
u32 = RTA_DATA(rtattr);
*u32 = tswap32(*u32);
break;
+ case QEMU_IFLA_AF_SPEC:
+ return target_to_host_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
+ target_to_host_data_spec_nlattr);
default:
qemu_log_mask(LOG_UNIMP, "Unknown target QEMU_IFLA type: %d\n",
rtattr->rta_type);
@@ -1438,7 +1684,7 @@ TargetFdTrans target_signalfd_trans = {
.host_to_target_data = host_to_target_data_signalfd,
};
-static abi_long swap_data_eventfd(void *buf, size_t len)
+static abi_long swap_data_u64(void *buf, size_t len)
{
uint64_t *counter = buf;
int i;
@@ -1456,13 +1702,16 @@ static abi_long swap_data_eventfd(void *buf, size_t len)
}
TargetFdTrans target_eventfd_trans = {
- .host_to_target_data = swap_data_eventfd,
- .target_to_host_data = swap_data_eventfd,
+ .host_to_target_data = swap_data_u64,
+ .target_to_host_data = swap_data_u64,
+};
+
+TargetFdTrans target_timerfd_trans = {
+ .host_to_target_data = swap_data_u64,
};
-#if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \
- (defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \
- defined(__NR_inotify_init1))
+#if defined(CONFIG_INOTIFY) && (defined(TARGET_NR_inotify_init) || \
+ defined(TARGET_NR_inotify_init1))
static abi_long host_to_target_data_inotify(void *buf, size_t len)
{
struct inotify_event *ev;