From nobody Mon Feb 9 06:00:57 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1675958223; cv=none; d=zohomail.com; s=zohoarc; b=EUr3jSf58OLkK5W5Elyxk2JZyOubmQiahEEmGrPNv5iGDSq1sTNy6CK+zCEpxVUbXfh8pgOM31v0lTS7kF+xVOFVVVmpNR4wiUwr7Gek1cbY2I9PD5h7z/Ez1LX6Jb/z66E0B4wiYWLYG0GnFjzpJz3LJvAUqvDbzZAIhZBOLdE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1675958223; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=yJepENBooB8tnoAsGQEI6uVGIC9PbSV8wMNtT1M+PBA=; b=etozU4g08jiqTORgVjjqmGSbWT9MlGlRlw5cXp5hShsxPm0DEZa+LeJlyOwhDBw89g6lGWFnSuS9oStAG1RfG/0Svj1rgmlOgT7hzF/yA/vVEmMxECCqLzgspoBoyAM5b3FJyLAwwrPmoSJuUvWIw0WT8uR6/uMlZcRQURBb0Og= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1675958223384947.0503403258562; Thu, 9 Feb 2023 07:57:03 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.492672.762347 (Exim 4.92) (envelope-from ) id 1pQ9Hm-0007ST-TG; Thu, 09 Feb 2023 15:56:34 +0000 Received: by outflank-mailman (output) from mailman id 492672.762347; Thu, 09 Feb 2023 15:56:34 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1pQ9Hm-0007SJ-O8; Thu, 09 Feb 2023 15:56:34 +0000 Received: by outflank-mailman (input) for mailman id 492672; Thu, 09 Feb 2023 15:56:33 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1pQ9Hl-0007Ak-2K for xen-devel@lists.xenproject.org; Thu, 09 Feb 2023 15:56:33 +0000 Received: from mail-ej1-x62f.google.com (mail-ej1-x62f.google.com [2a00:1450:4864:20::62f]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 519d4f8f-a892-11ed-933c-83870f6b2ba8; Thu, 09 Feb 2023 16:56:30 +0100 (CET) Received: by mail-ej1-x62f.google.com with SMTP id c26so2920514ejz.10 for ; Thu, 09 Feb 2023 07:56:30 -0800 (PST) Received: from dsemenets-HP-EliteBook-850-G8-Notebook-PC.. ([91.219.254.72]) by smtp.gmail.com with ESMTPSA id v1-20020a170906b00100b0087862f45a29sm1027594ejy.174.2023.02.09.07.56.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Feb 2023 07:56:29 -0800 (PST) X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 519d4f8f-a892-11ed-933c-83870f6b2ba8 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=yJepENBooB8tnoAsGQEI6uVGIC9PbSV8wMNtT1M+PBA=; b=lVKyPCvi1P3BzjR0R1P0UuDTd3etXpBDEHEpBz7XajqUzfGRqEpK4po3AHGdPahnBc feUq7TBn90f16l37u1nPgV/yLIRGA5NX9pMqkhxg4XZj4tB6TAiqcqqymDcIF3Qvk6RB ILPb/cM3Ng3Q1YtDovAUKtz1OkZqVPikWXRT6m7SlWQdkcNA9Vb13DYryFoedH8FBcJD hFKZM8WmV3uE01vui46Vv3UN3kRpwrPEXG8OOVgXvtqdWRLeU3/DhcrqVfYZk3S2E1+V vdjEynY77IIIQVKifqGBl206Bb3TgRsKSb2LTpUXzjG/2Qu3bh7muNrFOvDtB8doU6Ed iVnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yJepENBooB8tnoAsGQEI6uVGIC9PbSV8wMNtT1M+PBA=; b=WMCrpxnE0t6PgSO/j5Vff/FQubXWxTvsjZDuBTiVcvJ9FJRzMz2k9F/yjKTrPXENSO tamHQUEnWo0Zl9cuWyHi/nZ/6yqSuDVs4Z5esLcUxdNB2R5pW1BwcvMgaeuHlL0hlk7g 6mqazOTzpF6RKjj+Qt7IVX9DVWsVxNHdnsOgDZlSpfpXO1xBn95OgrmdqGuggG+lbUBq zu70guwuIlkcmfz000OA+4/kHdiSPxJG2DAdF85SeTRtsb+vTIOPiobOK62i2TPO/JNd gv63Kj9pvMr9/OgfNzXrJ4/WY0+uBLYJPThoLpRo/qALHb4ExsV2exxRFlaUNPK+xEaS hsaw== X-Gm-Message-State: AO0yUKXLB2/EaB0PDo8/Vs9mztdFxq5neCWCwxk8vgxNTlSA49i5NQR4 f+Rdcor44cYtPp7YZ0moyiBOlgKIBOIn4A== X-Google-Smtp-Source: AK7set81phE31Bybl/PFIIPg1DndlV9xZvdjfkV6IeUrl6A1qoPYapdjwju8W1yUblqTS9BP/VV9og== X-Received: by 2002:a17:906:1d2:b0:893:526b:c77b with SMTP id 18-20020a17090601d200b00893526bc77bmr12880215ejj.7.1675958189713; Thu, 09 Feb 2023 07:56:29 -0800 (PST) From: dmitry.semenets@gmail.com To: xen-devel@lists.xenproject.org Cc: Dmytro Semenets , Wei Liu , Anthony PERARD , Juergen Gross , Oleksandr Andrushchenko , Anastasiia Lukianenko Subject: [RFC PATCH v4 3/9] tools/xlpcid: Add xlpcid daemon Date: Thu, 9 Feb 2023 17:55:57 +0200 Message-Id: <20230209155604.2753219-4-dmitry.semenets@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230209155604.2753219-1-dmitry.semenets@gmail.com> References: <20230209155604.2753219-1-dmitry.semenets@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1675958225534100001 Content-Type: text/plain; charset="utf-8" From: Dmytro Semenets Add draft version of pcid server (based on vchan-node2), which can receive messages from the client. Add essential functionality to handle pcid protocol: - define required constants - prepare for handling remote requests - prepare and send an error packet Signed-off-by: Dmytro Semenets Signed-off-by: Oleksandr Andrushchenko Signed-off-by: Anastasiia Lukianenko --- tools/Makefile | 1 + tools/configure | 8 +- tools/configure.ac | 1 + tools/hotplug/FreeBSD/rc.d/xlpcid.in | 75 +++ tools/hotplug/Linux/init.d/xlpcid.in | 76 ++++ tools/hotplug/Linux/systemd/Makefile | 1 + .../hotplug/Linux/systemd/xenpcid.service.in | 10 + tools/hotplug/NetBSD/rc.d/xlpcid.in | 75 +++ tools/include/xen-pcid.h | 95 ++++ tools/libs/light/Makefile | 1 + tools/libs/light/libxl_pci.c | 128 ++++++ tools/libs/light/libxl_pcid.c | 428 ++++++++++++++++++ tools/xlpcid/Makefile | 52 +++ tools/xlpcid/bash-completion | 20 + tools/xlpcid/xlpcid.c | 213 +++++++++ 15 files changed, 1182 insertions(+), 2 deletions(-) create mode 100644 tools/hotplug/FreeBSD/rc.d/xlpcid.in create mode 100644 tools/hotplug/Linux/init.d/xlpcid.in create mode 100644 tools/hotplug/Linux/systemd/xenpcid.service.in create mode 100644 tools/hotplug/NetBSD/rc.d/xlpcid.in create mode 100644 tools/include/xen-pcid.h create mode 100644 tools/libs/light/libxl_pcid.c create mode 100644 tools/xlpcid/Makefile create mode 100644 tools/xlpcid/bash-completion create mode 100644 tools/xlpcid/xlpcid.c diff --git a/tools/Makefile b/tools/Makefile index 4906fdbc23..5a99f7bb61 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -30,6 +30,7 @@ endif SUBDIRS-y +=3D xenpmd SUBDIRS-$(CONFIG_GOLANG) +=3D golang SUBDIRS-y +=3D xl +SUBDIRS-y +=3D xlpcid SUBDIRS-y +=3D helpers SUBDIRS-$(CONFIG_X86) +=3D xenpaging SUBDIRS-$(CONFIG_X86) +=3D debugger diff --git a/tools/configure b/tools/configure index dae377c982..0cd6edb6ca 100755 --- a/tools/configure +++ b/tools/configure @@ -2455,7 +2455,7 @@ ac_compiler_gnu=3D$ac_cv_c_compiler_gnu =20 =20 =20 -ac_config_files=3D"$ac_config_files ../config/Tools.mk hotplug/common/hotp= lugpath.sh hotplug/FreeBSD/rc.d/xencommons hotplug/FreeBSD/rc.d/xendriverdo= main hotplug/Linux/init.d/sysconfig.xencommons hotplug/Linux/init.d/sysconf= ig.xendomains hotplug/Linux/init.d/xen-watchdog hotplug/Linux/init.d/xencom= mons hotplug/Linux/init.d/xendomains hotplug/Linux/init.d/xendriverdomain h= otplug/Linux/launch-xenstore hotplug/Linux/vif-setup hotplug/Linux/xen-hotp= lug-common.sh hotplug/Linux/xendomains hotplug/NetBSD/rc.d/xencommons hotpl= ug/NetBSD/rc.d/xendriverdomain ocaml/libs/xs/paths.ml ocaml/xenstored/paths= .ml ocaml/xenstored/oxenstored.conf" +ac_config_files=3D"$ac_config_files ../config/Tools.mk hotplug/common/hotp= lugpath.sh hotplug/FreeBSD/rc.d/xencommons hotplug/FreeBSD/rc.d/xendriverdo= main hotplug/FreeBSD/rc.d/xlpcid hotplug/Linux/init.d/sysconfig.xencommons = hotplug/Linux/init.d/sysconfig.xendomains hotplug/Linux/init.d/xlpcid hotpl= ug/Linux/init.d/xen-watchdog hotplug/Linux/init.d/xencommons hotplug/Linux/= init.d/xendomains hotplug/Linux/init.d/xendriverdomain hotplug/Linux/launch= -xenstore hotplug/Linux/vif-setup hotplug/Linux/xen-hotplug-common.sh hotpl= ug/Linux/xendomains hotplug/NetBSD/rc.d/xencommons hotplug/NetBSD/rc.d/xend= riverdomain hotplug/NetBSD/rc.d/xlpcid ocaml/libs/xs/paths.ml ocaml/xenstor= ed/paths.ml ocaml/xenstored/oxenstored.conf" =20 ac_config_headers=3D"$ac_config_headers config.h" =20 @@ -10081,7 +10081,7 @@ fi =20 if test "x$systemd" =3D "xy"; then : =20 - ac_config_files=3D"$ac_config_files hotplug/Linux/systemd/proc-xen.mou= nt hotplug/Linux/systemd/xen-init-dom0.service hotplug/Linux/systemd/xen-qe= mu-dom0-disk-backend.service hotplug/Linux/systemd/xen-watchdog.service hot= plug/Linux/systemd/xenconsoled.service hotplug/Linux/systemd/xendomains.ser= vice hotplug/Linux/systemd/xendriverdomain.service hotplug/Linux/systemd/xe= nstored.service" + ac_config_files=3D"$ac_config_files hotplug/Linux/systemd/proc-xen.mou= nt hotplug/Linux/systemd/xen-init-dom0.service hotplug/Linux/systemd/xen-qe= mu-dom0-disk-backend.service hotplug/Linux/systemd/xen-watchdog.service hot= plug/Linux/systemd/xenconsoled.service hotplug/Linux/systemd/xendomains.ser= vice hotplug/Linux/systemd/xendriverdomain.service hotplug/Linux/systemd/xe= nstored.service hotplug/Linux/systemd/xenpcid.service" =20 =20 fi @@ -10946,8 +10946,10 @@ do "hotplug/common/hotplugpath.sh") CONFIG_FILES=3D"$CONFIG_FILES hotplug= /common/hotplugpath.sh" ;; "hotplug/FreeBSD/rc.d/xencommons") CONFIG_FILES=3D"$CONFIG_FILES hotpl= ug/FreeBSD/rc.d/xencommons" ;; "hotplug/FreeBSD/rc.d/xendriverdomain") CONFIG_FILES=3D"$CONFIG_FILES = hotplug/FreeBSD/rc.d/xendriverdomain" ;; + "hotplug/FreeBSD/rc.d/xlpcid") CONFIG_FILES=3D"$CONFIG_FILES hotplug/F= reeBSD/rc.d/xlpcid" ;; "hotplug/Linux/init.d/sysconfig.xencommons") CONFIG_FILES=3D"$CONFIG_F= ILES hotplug/Linux/init.d/sysconfig.xencommons" ;; "hotplug/Linux/init.d/sysconfig.xendomains") CONFIG_FILES=3D"$CONFIG_F= ILES hotplug/Linux/init.d/sysconfig.xendomains" ;; + "hotplug/Linux/init.d/xlpcid") CONFIG_FILES=3D"$CONFIG_FILES hotplug/L= inux/init.d/xlpcid" ;; "hotplug/Linux/init.d/xen-watchdog") CONFIG_FILES=3D"$CONFIG_FILES hot= plug/Linux/init.d/xen-watchdog" ;; "hotplug/Linux/init.d/xencommons") CONFIG_FILES=3D"$CONFIG_FILES hotpl= ug/Linux/init.d/xencommons" ;; "hotplug/Linux/init.d/xendomains") CONFIG_FILES=3D"$CONFIG_FILES hotpl= ug/Linux/init.d/xendomains" ;; @@ -10958,6 +10960,7 @@ do "hotplug/Linux/xendomains") CONFIG_FILES=3D"$CONFIG_FILES hotplug/Linu= x/xendomains" ;; "hotplug/NetBSD/rc.d/xencommons") CONFIG_FILES=3D"$CONFIG_FILES hotplu= g/NetBSD/rc.d/xencommons" ;; "hotplug/NetBSD/rc.d/xendriverdomain") CONFIG_FILES=3D"$CONFIG_FILES h= otplug/NetBSD/rc.d/xendriverdomain" ;; + "hotplug/NetBSD/rc.d/xlpcid") CONFIG_FILES=3D"$CONFIG_FILES hotplug/Ne= tBSD/rc.d/xlpcid" ;; "ocaml/libs/xs/paths.ml") CONFIG_FILES=3D"$CONFIG_FILES ocaml/libs/xs/= paths.ml" ;; "ocaml/xenstored/paths.ml") CONFIG_FILES=3D"$CONFIG_FILES ocaml/xensto= red/paths.ml" ;; "ocaml/xenstored/oxenstored.conf") CONFIG_FILES=3D"$CONFIG_FILES ocaml= /xenstored/oxenstored.conf" ;; @@ -10970,6 +10973,7 @@ do "hotplug/Linux/systemd/xendomains.service") CONFIG_FILES=3D"$CONFIG_FI= LES hotplug/Linux/systemd/xendomains.service" ;; "hotplug/Linux/systemd/xendriverdomain.service") CONFIG_FILES=3D"$CONF= IG_FILES hotplug/Linux/systemd/xendriverdomain.service" ;; "hotplug/Linux/systemd/xenstored.service") CONFIG_FILES=3D"$CONFIG_FIL= ES hotplug/Linux/systemd/xenstored.service" ;; + "hotplug/Linux/systemd/xenpcid.service") CONFIG_FILES=3D"$CONFIG_FILES= hotplug/Linux/systemd/xenpcid.service" ;; =20 *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac diff --git a/tools/configure.ac b/tools/configure.ac index 3a2f6a2da9..d2b22e94a9 100644 --- a/tools/configure.ac +++ b/tools/configure.ac @@ -489,6 +489,7 @@ AS_IF([test "x$systemd" =3D "xy"], [ hotplug/Linux/systemd/xendomains.service hotplug/Linux/systemd/xendriverdomain.service hotplug/Linux/systemd/xenstored.service + hotplug/Linux/systemd/xenpcid.service ]) ]) =20 diff --git a/tools/hotplug/FreeBSD/rc.d/xlpcid.in b/tools/hotplug/FreeBSD/r= c.d/xlpcid.in new file mode 100644 index 0000000000..ad414c25ba --- /dev/null +++ b/tools/hotplug/FreeBSD/rc.d/xlpcid.in @@ -0,0 +1,75 @@ +#! /bin/bash +# +# xlpcid +# +# description: Run xlpcid daemon +### BEGIN INIT INFO +# Provides: xlpcid +# Short-Description: Start/stop xlpcid +# Description: Run xlpcid daemon +### END INIT INFO +# + +. @XEN_SCRIPT_DIR@/hotplugpath.sh + +xencommons_config=3D@CONFIG_DIR@/@CONFIG_LEAF_DIR@ + +test -f $xencommons_config/xencommons && . $xencommons_config/xencommons + +XLPCID_PIDFILE=3D"@XEN_RUN_DIR@/xlpcid.pid" + +# Source function library. +if [ -e /etc/init.d/functions ] ; then + . /etc/init.d/functions +elif [ -e /lib/lsb/init-functions ] ; then + . /lib/lsb/init-functions + success () { + log_success_msg $* + } + failure () { + log_failure_msg $* + } +else + success () { + echo $* + } + failure () { + echo $* + } +fi + +start() { + echo Starting xlpcid... + ${sbindir}/xlpcid --pidfile=3D$XLPCID_PIDFILE $XLPCID_ARGS +} + +stop() { + echo Stopping xl pcid... + if read 2>/dev/null <$XLPCID_PIDFILE pid; then + kill $pid + while kill -9 $pid >/dev/null 2>&1; do sleep 1; done + rm -f $XLPCID_PIDFILE + fi +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + ;; + condrestart) + stop + start + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart}" + exit 1 +esac diff --git a/tools/hotplug/Linux/init.d/xlpcid.in b/tools/hotplug/Linux/ini= t.d/xlpcid.in new file mode 100644 index 0000000000..d8e38501a7 --- /dev/null +++ b/tools/hotplug/Linux/init.d/xlpcid.in @@ -0,0 +1,76 @@ +#! /bin/bash +# +# xlpcid +# +# description: Run xlpcid daemon +### BEGIN INIT INFO +# Provides: xlpcid +# Short-Description: Start/stop xlpcid +# Description: Run xlpcid daemon +### END INIT INFO +# + +. @XEN_SCRIPT_DIR@/hotplugpath.sh + +xencommons_config=3D@CONFIG_DIR@/@CONFIG_LEAF_DIR@ + +test -f $xencommons_config/xencommons && . $xencommons_config/xencommons + +XLPCID_PIDFILE=3D"@XEN_RUN_DIR@/xlpcid.pid" + +# Source function library. +if [ -e /etc/init.d/functions ] ; then + . /etc/init.d/functions +elif [ -e /lib/lsb/init-functions ] ; then + . /lib/lsb/init-functions + success () { + log_success_msg $* + } + failure () { + log_failure_msg $* + } +else + success () { + echo $* + } + failure () { + echo $* + } +fi + +start() { + echo Starting xlpcid... + ${sbindir}/xlpcid --pidfile=3D$XLPCID_PIDFILE $XLPCID_ARGS +} + +stop() { + echo Stopping xl pcid... + if read 2>/dev/null <$XLPCID_PIDFILE pid; then + kill $pid + while kill -9 $pid >/dev/null 2>&1; do sleep 1; done + rm -f $XLPCID_PIDFILE + fi +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + ;; + condrestart) + stop + start + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart}" + exit 1 +esac + diff --git a/tools/hotplug/Linux/systemd/Makefile b/tools/hotplug/Linux/sys= temd/Makefile index e29889156d..49f0f87296 100644 --- a/tools/hotplug/Linux/systemd/Makefile +++ b/tools/hotplug/Linux/systemd/Makefile @@ -12,6 +12,7 @@ XEN_SYSTEMD_SERVICE +=3D xendomains.service XEN_SYSTEMD_SERVICE +=3D xen-watchdog.service XEN_SYSTEMD_SERVICE +=3D xen-init-dom0.service XEN_SYSTEMD_SERVICE +=3D xendriverdomain.service +XEN_SYSTEMD_SERVICE +=3D xenpcid.service =20 ALL_XEN_SYSTEMD :=3D $(XEN_SYSTEMD_MODULES) \ $(XEN_SYSTEMD_MOUNT) \ diff --git a/tools/hotplug/Linux/systemd/xenpcid.service.in b/tools/hotplug= /Linux/systemd/xenpcid.service.in new file mode 100644 index 0000000000..b0bfd72734 --- /dev/null +++ b/tools/hotplug/Linux/systemd/xenpcid.service.in @@ -0,0 +1,10 @@ +[Unit] +Description=3DXen PCI host daemon +ConditionVirtualization=3Dxen + +[Service] +Type=3Dforking +ExecStart=3D@sbindir@/xlpcid + +[Install] +WantedBy=3Dmulti-user.target diff --git a/tools/hotplug/NetBSD/rc.d/xlpcid.in b/tools/hotplug/NetBSD/rc.= d/xlpcid.in new file mode 100644 index 0000000000..ad414c25ba --- /dev/null +++ b/tools/hotplug/NetBSD/rc.d/xlpcid.in @@ -0,0 +1,75 @@ +#! /bin/bash +# +# xlpcid +# +# description: Run xlpcid daemon +### BEGIN INIT INFO +# Provides: xlpcid +# Short-Description: Start/stop xlpcid +# Description: Run xlpcid daemon +### END INIT INFO +# + +. @XEN_SCRIPT_DIR@/hotplugpath.sh + +xencommons_config=3D@CONFIG_DIR@/@CONFIG_LEAF_DIR@ + +test -f $xencommons_config/xencommons && . $xencommons_config/xencommons + +XLPCID_PIDFILE=3D"@XEN_RUN_DIR@/xlpcid.pid" + +# Source function library. +if [ -e /etc/init.d/functions ] ; then + . /etc/init.d/functions +elif [ -e /lib/lsb/init-functions ] ; then + . /lib/lsb/init-functions + success () { + log_success_msg $* + } + failure () { + log_failure_msg $* + } +else + success () { + echo $* + } + failure () { + echo $* + } +fi + +start() { + echo Starting xlpcid... + ${sbindir}/xlpcid --pidfile=3D$XLPCID_PIDFILE $XLPCID_ARGS +} + +stop() { + echo Stopping xl pcid... + if read 2>/dev/null <$XLPCID_PIDFILE pid; then + kill $pid + while kill -9 $pid >/dev/null 2>&1; do sleep 1; done + rm -f $XLPCID_PIDFILE + fi +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + ;; + condrestart) + stop + start + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart}" + exit 1 +esac diff --git a/tools/include/xen-pcid.h b/tools/include/xen-pcid.h new file mode 100644 index 0000000000..098118a0c3 --- /dev/null +++ b/tools/include/xen-pcid.h @@ -0,0 +1,95 @@ +/* + Common definitions for Xen PCI client-server protocol. + Copyright (C) 2021 EPAM Systems Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + SPDX-License-Identifier: LGPL-2.1+ +*/ + +#ifndef XEN_PCID_H +#define XEN_PCID_H + +#define PCID_SRV_NAME "pcid" +#define PCID_XS_TOKEN "pcid-token" + +#define PCI_RECEIVE_BUFFER_SIZE 4096 +#define PCI_MAX_SIZE_RX_BUF MB(1) + +/* + *************************************************************************= ****** + * Common request and response structures used be the pcid remote protocol= are + * described below. + *************************************************************************= ****** + * Request: + * +-------------+--------------+-----------------------------------------= -----+ + * | Field | Type | Comment = | + * +-------------+--------------+-----------------------------------------= -----+ + * | cmd | string | String identifying the command = | + * +-------------+--------------+-----------------------------------------= -----+ + * + * Response: + * +-------------+--------------+-----------------------------------------= -----+ + * | Field | Type | Comment = | + * +-------------+--------------+-----------------------------------------= -----+ + * | resp | string | Command string as in the request = | + * +-------------+--------------+-----------------------------------------= -----+ + * | error | string | "okay", "failed" = | + * +-------------+--------------+-----------------------------------------= -----+ + * | error_desc | string | Optional error description string = | + * +-------------+--------------+-----------------------------------------= -----+ + * + * Notes. + * 1. Every request and response must contain the above mandatory structur= es. + * 2. In case if a bad packet or an unknown command received by the server= side + * a valid reply with the corresponding error code must be sent to the cli= ent. + * + * Requests and responses, which require SBDF as part of their payload, mu= st + * use the following convention for encoding SBDF value: + * + * pci_device object: + * +-------------+--------------+-----------------------------------------= -----+ + * | Field | Type | Comment = | + * +-------------+--------------+-----------------------------------------= -----+ + * | sbdf | string | SBDF string in form SSSS:BB:DD.F = | + * +-------------+--------------+-----------------------------------------= -----+ + */ + +/* Fileld names */ +#define PCID_MSG_FIELD_CMD "cmd" + +#define PCID_MSG_FIELD_RESP "resp" +#define PCID_MSG_FIELD_ERR "error" +#define PCID_MSG_FIELD_ERR_DESC "error_desc" + +/* pci_device object fields. */ +#define PCID_MSG_FIELD_SBDF "sbdf" + +/* Error values */ +#define PCID_MSG_ERR_OK "okay" +#define PCID_MSG_ERR_FAILED "failed" +#define PCID_MSG_ERR_NA "NA" + +#define PCID_SBDF_FMT "%04x:%02x:%02x.%01x" + +int libxl_pcid_process(libxl_ctx *ctx); + +#endif /* XEN_PCID_H */ + +/* + * Local variables: + * mode: C + * c-file-style: "linux" + * indent-tabs-mode: t + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/tools/libs/light/Makefile b/tools/libs/light/Makefile index 0941ad2cf4..72997eaac9 100644 --- a/tools/libs/light/Makefile +++ b/tools/libs/light/Makefile @@ -71,6 +71,7 @@ OBJS-y +=3D libxl.o OBJS-y +=3D libxl_create.o OBJS-y +=3D libxl_dm.o OBJS-y +=3D libxl_pci.o +OBJS-y +=3D libxl_pcid.o OBJS-y +=3D libxl_vchan.o OBJS-y +=3D libxl_dom.o OBJS-y +=3D libxl_exec.o diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c index f4c4f17545..3d9ed0d50c 100644 --- a/tools/libs/light/libxl_pci.c +++ b/tools/libs/light/libxl_pci.c @@ -18,6 +18,10 @@ =20 #include "libxl_internal.h" =20 +#include + +#include "libxl_vchan.h" + #define PCI_BDF "%04x:%02x:%02x.%01x" #define PCI_BDF_SHORT "%02x:%02x.%01x" #define PCI_BDF_VDEVFN "%04x:%02x:%02x.%01x@%02x" @@ -25,6 +29,130 @@ #define PCI_BDF_XSPATH "%04x-%02x-%02x-%01x" #define PCI_PT_QDEV_ID "pci-pt-%02x_%02x.%01x" =20 +static int pci_handle_response(libxl__gc *gc, + const libxl__json_object *response, + libxl__json_object **result) +{ + const libxl__json_object *command_obj; + const libxl__json_object *err_obj; + char *command_name; + int ret =3D 0; + + *result =3D NULL; + + command_obj =3D libxl__json_map_get(PCID_MSG_FIELD_RESP, response, JSO= N_STRING); + if (!command_obj) { + /* This is an unsupported or bad response. */ + return 0; + } + + err_obj =3D libxl__json_map_get(PCID_MSG_FIELD_ERR, response, JSON_STR= ING); + if (!err_obj) { + /* Bad packet without error code field. */ + return 0; + } + + if (strcmp(err_obj->u.string, PCID_MSG_ERR_OK) !=3D 0) { + const libxl__json_object *err_desc_obj; + + /* The response may contain an optional error string. */ + err_desc_obj =3D libxl__json_map_get(PCID_MSG_FIELD_ERR_DESC, + response, JSON_STRING); + if (err_desc_obj) + LOG(ERROR, "%s", err_desc_obj->u.string); + else + LOG(ERROR, "%s", err_obj->u.string); + return ERROR_FAIL; + } + + command_name =3D command_obj->u.string; + LOG(DEBUG, "command: %s", command_name); + + return ret; +} + +#define CONVERT_YAJL_GEN_TO_STATUS(gen) \ + ((gen) =3D=3D yajl_gen_status_ok ? yajl_status_ok : yajl_status_error) + +static char *pci_prepare_request(libxl__gc *gc, yajl_gen gen, char *cmd, + libxl__json_object *args) +{ + const unsigned char *buf; + libxl_yajl_length len; + yajl_gen_status sts; + yajl_status ret; + char *request =3D NULL; + int rc; + + ret =3D CONVERT_YAJL_GEN_TO_STATUS(yajl_gen_map_open(gen)); + if (ret !=3D yajl_status_ok) + return NULL; + + rc =3D libxl__vchan_field_add_string(gc, gen, PCID_MSG_FIELD_CMD, cmd); + if (rc) + return NULL; + + if (args) { + int idx =3D 0; + libxl__json_map_node *node =3D NULL; + + assert(args->type =3D=3D JSON_MAP); + for (idx =3D 0; idx < args->u.map->count; idx++) { + if (flexarray_get(args->u.map, idx, (void**)&node) !=3D 0) + break; + + ret =3D CONVERT_YAJL_GEN_TO_STATUS(libxl__yajl_gen_asciiz(gen,= node->map_key)); + if (ret !=3D yajl_status_ok) + return NULL; + ret =3D libxl__json_object_to_yajl_gen(gc, gen, node->obj); + if (ret !=3D yajl_status_ok) + return NULL; + } + } + ret =3D CONVERT_YAJL_GEN_TO_STATUS(yajl_gen_map_close(gen)); + if (ret !=3D yajl_status_ok) + return NULL; + + sts =3D yajl_gen_get_buf(gen, &buf, &len); + if (sts !=3D yajl_gen_status_ok) + return NULL; + + request =3D libxl__sprintf(gc, "%s", buf); + + vchan_dump_gen(gc, gen); + + return request; +} + +struct vchan_info *pci_vchan_get_client(libxl__gc *gc); +struct vchan_info *pci_vchan_get_client(libxl__gc *gc) +{ + struct vchan_info *vchan; + + vchan =3D libxl__zalloc(gc, sizeof(*vchan)); + if (!vchan) + goto out; + vchan->state =3D vchan_new_client(gc, PCID_SRV_NAME); + if (!(vchan->state)) { + vchan =3D NULL; + goto out; + } + + vchan->handle_response =3D pci_handle_response; + vchan->prepare_request =3D pci_prepare_request; + vchan->receive_buf_size =3D PCI_RECEIVE_BUFFER_SIZE; + vchan->max_buf_size =3D PCI_MAX_SIZE_RX_BUF; + +out: + return vchan; +} + +void pci_vchan_free(libxl__gc *gc, struct vchan_info *vchan); +void pci_vchan_free(libxl__gc *gc, struct vchan_info *vchan) +{ + vchan_fini_one(gc, vchan->state); +} + static unsigned int pci_encode_bdf(libxl_device_pci *pci) { unsigned int value; diff --git a/tools/libs/light/libxl_pcid.c b/tools/libs/light/libxl_pcid.c new file mode 100644 index 0000000000..2ce8f1504d --- /dev/null +++ b/tools/libs/light/libxl_pcid.c @@ -0,0 +1,428 @@ +/* + Utils for xl pcid daemon + + Copyright (C) 2021 EPAM Systems Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; If not, see . + */ + +#define _GNU_SOURCE // required for strchrnul() + +#include "libxl_osdeps.h" /* must come before any other headers */ + +#include "libxl_internal.h" +#include "libxl_vchan.h" + +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#define DOM0_ID 0 + +struct vchan_client { + XEN_LIST_ENTRY(struct vchan_client) list; + + /* This is the watch entry fired for this client. */ + char **watch_ret; + /* Length of the watch_ret[XS_WATCH_PATH]. */ + size_t watch_len; + + struct vchan_info info; + + /* + * This context is used by the processing loop to create its own gc + * and use it while processing commands, so we do not get OOM. + */ + libxl_ctx *ctx; + /* This gc holds all allocations made for the client needs itself. */ + libxl__gc gc[1]; + pthread_t run_thread; +}; + +static XEN_LIST_HEAD(clients_list, struct vchan_client) vchan_clients; + +static pthread_mutex_t vchan_client_mutex; + +static int make_error_reply(libxl__gc *gc, yajl_gen gen, char *desc, + char *command_name) +{ + int rc; + + rc =3D libxl__vchan_field_add_string(gc, gen, PCID_MSG_FIELD_RESP, + command_name); + if (rc) + return rc; + + rc =3D libxl__vchan_field_add_string(gc, gen, PCID_MSG_FIELD_ERR, + PCID_MSG_ERR_FAILED); + if (rc) + return rc; + + rc =3D libxl__vchan_field_add_string(gc, gen, PCID_MSG_FIELD_ERR_DESC,= desc); + if (rc) + return rc; + + return 0; +} + +static int pcid_handle_request(libxl__gc *gc, yajl_gen gen, + const libxl__json_object *request) +{ + const libxl__json_object *command_obj; + libxl__json_object *command_response =3D NULL; + char *command_name; + int ret =3D 0; + + yajl_gen_map_open(gen); + + command_obj =3D libxl__json_map_get(PCID_MSG_FIELD_CMD, request, JSON_= STRING); + if (!command_obj) { + /* This is an unsupported or bad request. */ + ret =3D make_error_reply(gc, gen, "Unsupported request or bad pack= et", + PCID_MSG_ERR_NA); + goto out; + } + + command_name =3D command_obj->u.string; + + /* + * This is an unsupported command: make a reply and proceed over + * the error path. + */ + ret =3D make_error_reply(gc, gen, "Unsupported command", + command_name); + if (!ret) + ret =3D ERROR_NOTFOUND; + + if (ret) { + /* + * The command handler on error must provide a valid response, + * so we don't need to add any other field below. + */ + ret =3D 0; + goto out; + } + + if (command_response) { + ret =3D libxl__json_object_to_yajl_gen(gc, gen, command_response); + if (ret) + goto out; + } + + ret =3D libxl__vchan_field_add_string(gc, gen, PCID_MSG_FIELD_RESP, + command_name); + if (ret) + goto out; + + ret =3D libxl__vchan_field_add_string(gc, gen, PCID_MSG_FIELD_ERR, + PCID_MSG_ERR_OK); +out: + yajl_gen_map_close(gen); + + vchan_dump_gen(gc, gen); + + return ret; +} + +static char *pcid_prepare_response(libxl__gc *gc, yajl_gen gen) +{ + const unsigned char *buf; + libxl_yajl_length len; + yajl_gen_status sts; + char *reply =3D NULL; + + sts =3D yajl_gen_get_buf(gen, &buf, &len); + if (sts !=3D yajl_gen_status_ok) + goto out; + + reply =3D libxl__sprintf(gc, "%s", buf); + + vchan_dump_gen(gc, gen); + +out: + return reply; +} + +static void server_fini_one(libxl__gc *gc, struct vchan_client *client) +{ + pthread_mutex_lock(&vchan_client_mutex); + XEN_LIST_REMOVE(client, list); + pthread_mutex_unlock(&vchan_client_mutex); + + GC_FREE; + free(client->watch_ret); + free(client); +} + +static bool is_vchan_exist(libxl_ctx *ctx, char *watch_dir) +{ + char **dir =3D NULL; + unsigned int nb; + bool ret =3D false; + + dir =3D xs_directory(ctx->xsh, XBT_NULL, watch_dir, &nb); + if (dir) { + free(dir); + ret =3D true; + } + return ret; +} + +static void *client_thread(void *arg) +{ + struct vchan_client *client =3D arg; + + while (true) { + int ret; + /* + * libvchan uses garbage collector for processing requests, + * so we create a new one each time we process a packet and + * dispose it right away to prevent OOM. + */ + GC_INIT(client->ctx); + ret =3D vchan_process_command(gc, &client->info); + GC_FREE; + + if ((ret =3D=3D ERROR_NOTFOUND) || (ret =3D=3D ERROR_INVAL)) + continue; + if (ret < 0) + break; + } + vchan_fini_one(client->gc, client->info.state); + server_fini_one(client->gc, client); + return NULL; +} + +#define DEFAULT_THREAD_STACKSIZE (24 * 1024) +/* NetBSD doesn't have PTHREAD_STACK_MIN. */ +#ifndef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 +#endif + +#define READ_THREAD_STACKSIZE \ + ((DEFAULT_THREAD_STACKSIZE < PTHREAD_STACK_MIN) ? \ + PTHREAD_STACK_MIN : DEFAULT_THREAD_STACKSIZE) + +static bool init_client_thread(libxl__gc *gc, struct vchan_client *new_cli= ent) +{ + + sigset_t set, old_set; + pthread_attr_t attr; + static size_t stack_size; +#ifdef USE_DLSYM + size_t (*getsz)(pthread_attr_t *attr); +#endif + + if (pthread_attr_init(&attr) !=3D 0) + return false; + if (!stack_size) { +#ifdef USE_DLSYM + getsz =3D dlsym(RTLD_DEFAULT, "__pthread_get_minstack"); + if (getsz) + stack_size =3D getsz(&attr); +#endif + if (stack_size < READ_THREAD_STACKSIZE) + stack_size =3D READ_THREAD_STACKSIZE; + } + if (pthread_attr_setstacksize(&attr, stack_size) !=3D 0) { + pthread_attr_destroy(&attr); + return false; + } + + sigfillset(&set); + pthread_sigmask(SIG_SETMASK, &set, &old_set); + + if (pthread_create(&new_client->run_thread, &attr, client_thread, + new_client) !=3D 0) { + pthread_sigmask(SIG_SETMASK, &old_set, NULL); + pthread_attr_destroy(&attr); + return false; + } + pthread_sigmask(SIG_SETMASK, &old_set, NULL); + pthread_attr_destroy(&attr); + + return true; +} + +static void init_new_client(libxl_ctx *ctx, libxl__gc *gc, + struct clients_list *list, char **watch_ret) +{ + struct vchan_client *new_client; + char *xs_path =3D watch_ret[XS_WATCH_PATH]; + + LOG(DEBUG, "New client at \"%s\"", xs_path); + + new_client =3D malloc(sizeof(*new_client)); + if (!new_client) { + LOGE(ERROR, "Failed to allocate new client at \"%s\"", xs_path); + return; + } + + memset(new_client, 0, sizeof(*new_client)); + + new_client->watch_ret =3D watch_ret; + new_client->watch_len =3D strlen(xs_path); + new_client->ctx =3D ctx; + /* + * Remember the GC of this client, so we can dispose its memory. + * Use it from now on. + */ + LIBXL_INIT_GC(new_client->gc[0], ctx); + + new_client->info.state =3D vchan_init_new_state(new_client->gc, DOM0_I= D, + xs_path, true); + if (!(new_client->info.state)) { + LOGE(ERROR, "Failed to add new client at \"%s\"", xs_path); + server_fini_one(new_client->gc, new_client); + return; + } + + new_client->info.handle_request =3D pcid_handle_request; + new_client->info.prepare_response =3D pcid_prepare_response; + new_client->info.receive_buf_size =3D PCI_RECEIVE_BUFFER_SIZE; + new_client->info.max_buf_size =3D PCI_MAX_SIZE_RX_BUF; + + if (!init_client_thread(new_client->gc, new_client)) { + LOGE(ERROR, "Failed to create client's thread for \"%s\"", xs_path= ); + server_fini_one(new_client->gc, new_client); + return; + } + + pthread_mutex_lock(&vchan_client_mutex); + XEN_LIST_INSERT_HEAD(&vchan_clients, new_client, list); + pthread_mutex_unlock(&vchan_client_mutex); +} + +static void terminate_clients(void) +{ + struct vchan_client *client; + + pthread_mutex_lock(&vchan_client_mutex); + XEN_LIST_FOREACH(client, &vchan_clients, list) { + pthread_join(client->run_thread, NULL); + } + pthread_mutex_unlock(&vchan_client_mutex); +} + +int libxl_pcid_process(libxl_ctx *ctx) +{ + GC_INIT(ctx); + char *xs_path, *str; + char **watch_ret; + unsigned int watch_num; + libxl_domid domid; + int ret; + + pthread_mutex_init(&vchan_client_mutex, NULL); + + str =3D xs_read(ctx->xsh, 0, "domid", NULL); + if (!str) { + LOGE(ERROR, "Can't read own domid\n"); + ret =3D -ENOENT; + goto out; + } + + ret =3D sscanf(str, "%d", &domid); + free(str); + if (ret !=3D 1) + { + LOGE(ERROR, "Own domid is not an integer\n"); + ret =3D -EINVAL; + goto out; + } + + xs_path =3D vchan_get_server_xs_path(gc, domid, PCID_SRV_NAME); + + /* Recreate the base folder: remove all leftovers. */ + ret =3D libxl__xs_rm_checked(gc, XBT_NULL, xs_path); + if (ret) + goto out; + + if (!xs_mkdir(CTX->xsh, XBT_NULL, xs_path)) + { + LOGE(ERROR, "xenstore mkdir failed: `%s'", xs_path); + ret =3D ERROR_FAIL; + goto out; + } + + /* Wait for vchan client to create a new UUID under the server's folde= r. */ + if (!xs_watch(CTX->xsh, xs_path, PCID_XS_TOKEN)) { + LOGE(ERROR, "xs_watch (%s) failed", xs_path); + ret =3D ERROR_FAIL; + goto out; + } + + while ((watch_ret =3D xs_read_watch(CTX->xsh, &watch_num))) { + struct vchan_client *client; + size_t len; + bool found; + + /* + * Any change under the base directory will fire an event, so we n= eed + * to filter if this is indeed a new client or it is because vchan + * server creates nodes under its UUID. + * + * Never try to instantiate a vchan server right under xs_path. + */ + if (!strcmp(watch_ret[XS_WATCH_PATH], xs_path)) + continue; + + found =3D false; + len =3D strlen(watch_ret[XS_WATCH_PATH]); + + pthread_mutex_lock(&vchan_client_mutex); + XEN_LIST_FOREACH(client, &vchan_clients, list) { + str =3D client->watch_ret[XS_WATCH_PATH]; + + if (strstr(watch_ret[XS_WATCH_PATH], str)) { + /* + * Base path is a substring of the current path, so it can= be: + * - a new node with different name, but starting with str + * - a subnode under str, so it will have '/' after str + * - same string + */ + if (len =3D=3D client->watch_len) { + found =3D true; + break; + } + if (len > client->watch_len) { + if (watch_ret[XS_WATCH_PATH][client->watch_len] =3D=3D= '/') { + found =3D true; + break; + } + } + } + } + pthread_mutex_unlock(&vchan_client_mutex); + + if (!found && is_vchan_exist(ctx, watch_ret[XS_WATCH_PATH])) + init_new_client(ctx, gc, &vchan_clients, watch_ret); + } + + xs_unwatch(CTX->xsh, xs_path, PCID_XS_TOKEN); + +out: + terminate_clients(); + GC_FREE; + pthread_mutex_destroy(&vchan_client_mutex); + return ret; +} diff --git a/tools/xlpcid/Makefile b/tools/xlpcid/Makefile new file mode 100644 index 0000000000..238b6ef02f --- /dev/null +++ b/tools/xlpcid/Makefile @@ -0,0 +1,52 @@ +# +# tools/xlpcid/Makefile +# + +XEN_ROOT =3D $(CURDIR)/../.. +include $(XEN_ROOT)/tools/Rules.mk + +CFLAGS +=3D -Wno-format-zero-length -Wmissing-declarations \ + -Wno-declaration-after-statement -Wformat-nonliteral +CFLAGS +=3D -fPIC + +CFLAGS +=3D $(PTHREAD_CFLAGS) +LDFLAGS +=3D $(PTHREAD_LDFLAGS) + +CFLAGS_XLPCID +=3D $(CFLAGS_libxenlight) +CFLAGS_XLPCID +=3D $(CFLAGS_libxenutil) +CFLAGS_XLPCID +=3D -Wshadow +CFLAGS_XLPCID +=3D $(CFLAGS_libxenvchan) + +#XL_OBJS-$(CONFIG_X86) =3D xl_psr.o +XLPCID_OBJS =3D xlpcid.o $(XLPCID_OBJS-y) + +$(XLPCID_OBJS): CFLAGS +=3D $(CFLAGS_libxentoollog) +$(XLPCID_OBJS): CFLAGS +=3D $(CFLAGS_XLPCID) +$(XLPCID_OBJS): CFLAGS +=3D -include $(XEN_ROOT)/tools/config.h # libxl_js= on.h needs it. + +.PHONY: all +all: xlpcid + +xlpcid: $(XLPCID_OBJS) + $(CC) $(LDFLAGS) -o $@ $(XLPCID_OBJS) $(LDLIBS_libxenutil) $(LDLIBS_libxe= nlight) $(LDLIBS_libxentoollog) $(LDLIBS_libxenvchan) -lyajl $(APPEND_LDFLA= GS) + +.PHONY: install +install: all + $(INSTALL_DIR) $(DESTDIR)$(sbindir) + $(INSTALL_DIR) $(DESTDIR)$(BASH_COMPLETION_DIR) + $(INSTALL_PROG) xlpcid $(DESTDIR)$(sbindir) + $(INSTALL_DATA) bash-completion $(DESTDIR)$(BASH_COMPLETION_DIR)/xlpcid + +.PHONY: uninstall +uninstall: + rm -f $(DESTDIR)$(BASH_COMPLETION_DIR)/xlpcid + rm -f $(DESTDIR)$(sbindir)/xlpcid + +.PHONY: clean +clean: + $(RM) *.o xlpcid $(DEPS_RM) + +distclean: clean + + +-include $(DEPS_INCLUDE) diff --git a/tools/xlpcid/bash-completion b/tools/xlpcid/bash-completion new file mode 100644 index 0000000000..578ef38b9f --- /dev/null +++ b/tools/xlpcid/bash-completion @@ -0,0 +1,20 @@ +# Copy this file to /etc/bash_completion.d/xl + +_xlpcid() +{ + local IFS=3D$'\n,' + + local cur opts xlpcid + COMPREPLY=3D() + cur=3D"${COMP_WORDS[COMP_CWORD]}" + xlpcid=3Dxlpcid + + if [[ $COMP_CWORD =3D=3D 1 ]] ; then + opts=3D`${xlpcid} help 2>/dev/null | sed '1,4d' | awk '/^ [^ ]/ {print $= 1}' | sed 's/$/ ,/g'` && COMPREPLY=3D( $(compgen -W "${opts}" -- ${cur}) ) + return 0 + fi + + return 0 +} + +complete -F _xlpcid -o nospace -o default xlpcid diff --git a/tools/xlpcid/xlpcid.c b/tools/xlpcid/xlpcid.c new file mode 100644 index 0000000000..cb5804341d --- /dev/null +++ b/tools/xlpcid/xlpcid.c @@ -0,0 +1,213 @@ +/* + Pcid daemon that acts as a server for the client in the libxl PCI + + Copyright (C) 2021 EPAM Systems Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; If not, see . + */ + +#define _GNU_SOURCE // required for strchrnul() + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +libxl_ctx *ctx; +xentoollog_logger_stdiostream *logger; +libxl_bitmap global_vm_affinity_mask; +libxl_bitmap global_hvm_affinity_mask; +libxl_bitmap global_pv_affinity_mask; +char *lockfile; +int logfile; + +static void help(void) +{ + fprintf(stderr, "Usage xlpcid [-ftTvp]\n") + fprintf(stderr, " --foreground - run in foreground mode\n"); + fprintf(stderr, " --pidfile - specify pid file\n"); + fprintf(stderr, " -t - Always use carriage-return-b= ased overwriting\n"); + fprintf(stderr, " for displaying progress mess= ages without scrolling\n"); + fprintf(stderr, " the screen. Without -t, this= is done only if stderr is a tty.\n"); + fprintf(stderr, " -T - Include timestamps and pid o= f the xl process in output.\n"); + fprintf(stderr, " -v - Verbose\n"); +} + +static void xlpcid_ctx_alloc(void) +{ + if (libxl_ctx_alloc(&ctx, LIBXL_VERSION, 0, (xentoollog_logger*)logger= )) { + fprintf(stderr, "cannot init xl context\n"); + exit(1); + } + + libxl_bitmap_init(&global_vm_affinity_mask); + libxl_bitmap_init(&global_hvm_affinity_mask); + libxl_bitmap_init(&global_pv_affinity_mask); +} + +static void xlpcid_ctx_free(void) +{ + libxl_bitmap_dispose(&global_pv_affinity_mask); + libxl_bitmap_dispose(&global_hvm_affinity_mask); + libxl_bitmap_dispose(&global_vm_affinity_mask); + if (ctx) { + libxl_ctx_free(ctx); + ctx =3D NULL; + } + if (logger) { + xtl_logger_destroy((xentoollog_logger*)logger); + logger =3D NULL; + } + if (lockfile) { + free(lockfile); + lockfile =3D NULL; + } +} + +static int do_daemonize(const char *name, const char *pidfile) +{ + char *fullname; + int nullfd, ret =3D 0; + + ret =3D libxl_create_logfile(ctx, name, &fullname); + if (ret) { + fprintf(stderr, "Failed to open logfile %s: %s", fullname, strerro= r(errno)); + exit(-1); + } + + logfile =3D open(fullname, O_WRONLY|O_CREAT|O_APPEND, 0644); + free(fullname); + assert(logfile >=3D 3); + + nullfd =3D open("/dev/null", O_RDONLY); + assert(nullfd >=3D 3); + + dup2(nullfd, 0); + dup2(logfile, 1); + dup2(logfile, 2); + + close(nullfd); + + if (daemon(0, 1)) { + perror("daemon"); + close(logfile); + return 1; + } + + if (pidfile) { + int fd =3D open(pidfile, O_RDWR | O_CREAT, S_IRUSR|S_IWUSR); + char *pid =3D NULL; + + if (fd =3D=3D -1) { + perror("Unable to open pidfile"); + exit(1); + } + + if (asprintf(&pid, "%ld\n", (long)getpid()) =3D=3D -1) { + perror("Formatting pid"); + exit(1); + } + + if (write(fd, pid, strlen(pid)) < 0) { + perror("Writing pid"); + exit(1); + } + + if (close(fd) < 0) { + perror("Closing pidfile"); + exit(1); + } + + free(pid); + } + + return ret; +} + +int main(int argc, char *argv[]) +{ + int opt =3D 0, daemonize =3D 1, ret =3D 0; + const char *pidfile =3D NULL; + unsigned int xtl_flags =3D 0; + bool progress_use_cr =3D 0; + bool timestamps =3D 0; + xentoollog_level minmsglevel =3D XTL_PROGRESS; + static const struct option opts[] =3D { + {"pidfile", 1, 0, 'p'}, + {"foreground", 0, 0, 'f'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} + }; + + while ((opt =3D getopt_long(argc, argv, "hftTvp:", opts, NULL)) !=3D -= 1) + switch (opt) { + case 'f': + daemonize =3D 0; + break; + case 'p': + pidfile =3D optarg; + break; + case 't': + timestamps =3D 1; + break; + case 'T': + progress_use_cr =3D 1; + break; + case 'v': + if (minmsglevel > 0) + minmsglevel--; + break; + case 'h': + help(); + exit(1); + break; + default: + fprintf(stderr, "Unknown option '%c'\n", opt); + break; + } + + if (progress_use_cr) + xtl_flags |=3D XTL_STDIOSTREAM_PROGRESS_USE_CR; + if (timestamps) + xtl_flags |=3D XTL_STDIOSTREAM_SHOW_DATE | XTL_STDIOSTREAM_SHOW_PI= D; + logger =3D xtl_createlogger_stdiostream(stderr, minmsglevel, xtl_flags= ); + if (!logger) + exit(EXIT_FAILURE); + + xlpcid_ctx_alloc(); + + if (daemonize) { + ret =3D do_daemonize("xlpcid", pidfile); + if (ret) { + ret =3D (ret =3D=3D 1) ? 0 : ret; + goto out_daemon; + } + } + + libxl_pcid_process(ctx); + +out_daemon: + xlpcid_ctx_free(); + exit(ret); +} --=20 2.34.1