Welcome to a talk about USB 9PFS, let's do a short introduction and a good one.
My name is Michael Graschick and here's my colleague, Ahmed, Patum.
We work at Pengentronics, a company located in Hillsheim.
We work mostly on embedded tasks for companies as we do consulting,
drive a development graphics and system integration.
Actually, this picture was taken in a special time once in a year
when all members of our companies travelling to one place
and then we just break all our development for the customers and talk about issues.
And then we try to figure out what could be possible solution to get something better done
and something like that.
And this leads me to the first question issues.
Do a lot of you would network embedded devices over NFS, how many of you?
Do you sometimes see issues by doing this?
For example, not the right privileges of your root file system,
or the root file system is not suitable.
How many of you would say it's a common issue?
Yeah, perfect.
And sometimes do you have the issues that you have to know network interface
on the embedded device available because you are developing on the network interface.
Perhaps a switch or something like that.
Okay, like two, three, four, five hands.
Yeah, always use otherwise because application needs it
and you need to debug something because it's running.
You know, it's a user space.
Okay.
Does anybody use NFS in some situations?
Okay, it's not so many.
But we do.
We now do an MPSF over is a USB-get at transport.
Some because a lot of embedded devices have an USB-get at port available
while the Ethernet port is not available.
And so what we thought about is to the way around
we connect the get at port to and host.
So it's exposing the file systems that we want to see
the embedded device over USB.
This is a little bit tricky because usually you see the other way around
when you plug in your phone.
It's actually also a get it and you see the file system of your mobile phone
but it's a different way around.
So you see the file system from the hard drive on your mobile on your desktop
in the embedded device.
This is actually the preferable way to debug the system.
So a lot of you usually see an MPFS in the wide
when you develop, for example, QMO.
You have an embedded device.
Your application stack could run in QMO.
By booting the root file system, you exported by the WITIO
and an MP device interface that is implemented in the QMO application.
But there's a lot of other client transports in the Linux kernel.
For example, the TCP stacks, and it's usually also possible to boot
and embed a device over an IP.
This is located in the file descriptor transport.
And then the, like I mentioned, the WITIO interface is available
in the kernel or there are different other specialties for data farming
and RDMA or upset.
The exported part, I was talking about the client part.
The exported part that is exporting the file system on the host,
is you can use two open source applications like NFS
Ganesha or Diodes.
NFS Ganesha is a little bit more complex,
and you can do a lot of NFS and stuff.
But here, Diodes is a simple way.
And it's easier to configure and run for a pass.
So what is an IPFS actually?
It's actually only a protocol.
It's a representation of data on another namespace.
And for this, you can, as I said,
there are different profiles.
It's actually from the 90s.
It's pretty old.
But they defined the L profile extra for Linux.
So you could map and hold file system over the 9PFS
with other operations that are specified.
Flash, more, read files and clunk and everything.
Sticks is another name for an older implementation.
That's an interesting story about it.
You don't have to export file systems.
You can also export different things.
And in that case, Sticks was used by LEGO.
Sticks on a brick is a robotic system from LEGO,
where you can expose the motors, sensors and motors
and everything over the 9PFS.
And they use a transport of infrared.
So they transport it to the host.
And then you can control in the rooms, the robots,
and they use 9PFS.
It's only another name for the same thing.
So 9PFS has some transport restrictions.
It must be reliable.
So UDP is not possible because you may not lose any package.
But USB is possible since you have bulk endpoints.
So you see a C checked and the C's endpoints are not being.
They're always reliable.
And the messages may not be a transport.
So every request needs to map to the same request
when it comes back.
This is another limitation.
And USB is a good transport for exactly this purpose.
We took an example by the serial gadget
where you have TX and RX endpoint and for this.
For UDP, we also took one endpoint for the request.
That we sent to the host and then we get the responses back.
By the other endpoint.
And we also only allocate one USB request per endpoint.
So it's much simpler.
So we don't have to household a lot of infrared transmissions.
And when a transmit is going on,
the transmit has to wait for the receiver to come back.
Until another MPFS request can be transmitted again.
They all get cut up in the link list.
So they will be catched up later when the request is available again.
For now, USB and I'm PFS got merged.
In Colonel Lennox, Colonel Version 612.
It's called TransNetUSBG.C.
And it also includes an forwarder since
she mentioned TCP demons, diode, and it has
Ganesha that do not from itself connect to the USB endpoint.
We needed something to map the 9P transmit to the USB endpoint.
And for this we added a forward Python script that you can use.
Getting into the details of the driver shortly.
It's actually not that sophisticated.
A lot of things were already available in the Colonel.
So we did actually just drive a good driver,
where we implemented some callbacks.
The 9P transport only needs a few of implementations like
a create, so the client that is requesting the transport
can attach to it.
This usually is a mount callback.
And then the clause is detaching it.
And the request is only queueing up the USB request
into the endpoint.
On the USB side, the
seggerget implementation is also not set.
Have you implemented the bind functions?
And the set for all function is actually only enabling.
It's enabling the device, so it knows it is present and
can go on with the transfers.
It's not set as to implement because everything was there.
It's a gadget side.
So here's a mount example if you want to use it.
On the gadget side, you have to set up the gadget.
Usually in a modern system and in a embedded system,
you have to get a tool and lift USB-GX.
Then PFAS is also already in part of the USB-GX.
So you can just ride the scheme file.
It's like a DT that's a little bit different.
We'll describe the gadget a little bit with all its parts.
And then you can load it and get configured with configFS.
And then all you need to do is call the mount callback as a mount function
or the mount call.
And then you pass the USB-G-Trans option to the mount call.
And to which parts you want to mount on your lock and file system.
On the outside, that's a little bit more complex because we have this transmitter
pison tool in between.
So we start the diode and then we only start the pison scripts
that is starting to forwarder.
If you have multiple devices available, you can also
set the right one with the past argument.
It's optional.
So I think that's it for the development part and I hand over to Ahmed.
Thank you, Michean.
So having garnered support is, of course, a necessary precondition to make
this viable.
So we don't want to patch the garnered to be able to use it.
But there are a lot more moving parts until we can have the same
development experience that we have with NFS.
And we want to go further than that and solve these solutions.
Problems have solutions for these problems.
That Michean showed in the first slides.
So first thing is how's the kernel loaded?
We want to use preferably the same protocol that loaded the kernel.
That's the kernel uses to load the kernel itself.
So that means we need an NFS support in the bootloader.
So we can just use the same mechanism during the whole debugging cycle.
And unfortunately, so with legacy gadgets, you could set some up via kernel
command line.
But with non-legacy gadgets, you can do that anymore.
You have configfs and you need to like create directories,
write files, and so on.
And it's more complicated and can be expressed in the kernel command line.
So you need a cooperating user space to set up the mount point.
And then we need to generate a root of S.
So for me, I usually work with Yachto about support packages.
So I want a root of S coming out of Yachto that I can use.
And that's what I'm going to show.
So first thing is I ported my PFS, which Micheal contributed
to Linux to Burbox.
It I didn't port the TCP back end, but I ported that I owe and
USB gadget transport.
And the nice thing is that the file system layer is really good in Burbox.
And you have a lot of convenience functions.
I'm going to show you in a demo later.
So it integrates really well with 9p.
So I want, yeah, I will show you in the demo what I mean with that.
So now Burbox can boot the kernel out of a 9p file system
exported over USB.
Then we need an inner trauma of S to set up a root file system for
with 9pfs.
We wrote a program for that, our S in it.
It's our S because it's written in Rust, but it's also an RD in it.
So it's a RAM disk in it.
And it's meant to be just a minimalistic, single, executable that you can
statically link.
And that will do the stuff that you need an inner trauma of S for for example.
It can mount at the inverted device or it can set up NFS root or
it can mount 9pfs.
So the inverted device in an AB system, you need to have some logic to
select which device you need.
And yeah, our S in it does that for you.
And here's an example.
This minus S that you might see is it's blue.
That means it's static linked.
I am using muzzle.
So I can just statically link again.
So let's see.
And with CPI or I create an inner trauma of S.
And then I have a single executable that I can use.
And yeah, it can just boot my system.
Then next step is my system.
It's a rootfs.
How to get the rootfs.
So the problem is if I unpack without pseudo.
I as a file set are being extracted.
We'll have my user ID.
And that's not good.
For example, if you have PASWD.
It's a suite binary.
And that means it will adopt the user ID of file itself.
When you execute it.
And it want to work nicely if something which is supposed to be
user ID root to use ID zero.
When it runs with my 1065 at the development server.
That's one to work.
And there is a solution for that already upstream in Poké or in O.A.
Core, which is run QEmoExport rootfs, which runs user space and F.S.
Demon under pseudo's fake root environment.
And as far as U.N.F.S.D. is concerned,
it's running with root.
It is seeing a rootfile system.
And it will send over.
NFS everything as it is.
As it is on the target.
So if a file has suite and UIDGID zero in the target rootfs,
it will have so over NFS as well.
And my colleague Enrico wrote Poké NFS root.
And in Prague, there was a Yachto summit or Yachto workshop or something.
He has a talk about that.
And what set does is that it listens on the package feed
from BitBake and continuously updates the rootfs.
So you can just build a package and see it pop up directly in your NFS root
without having to reboot.
And what I did additionally to that,
that I thought run QEmoExport rootfs is a generic name,
but it's basically only doing NFS.
I extended it so it can do 9p.
That was just some refactoring.
What needed a bit more work was the lobotomy I had to do to diet.
So diet is a bit more sophisticated than UNFSD.
And it does stuff like look up users and check groups and so on.
And it doesn't like at all that the runs inside a fake root argument,
a fake root environment.
But with some strategically placed returns and commented out code,
it's fine with running the fake root environment.
And yeah, so we have everything in place.
And I can show you that demo.
I need to, yeah.
Yeah, so that's some arm V7 board.
You see here, barbox has booted up.
You see it has created a multi gadget with a fast boot.
You want to set, but also with 9pfs.
So you can export multiple function over USB.
You could also export a console so you just need USB.
You will see here there is an auto mount entry.
It will automatically detect that there is a 9p.
You can see a gadget that has been set up and create for use this path.
And on first access to this path, it will mount remote file system.
It's not mounted yet.
So these auto mounts are only mounted when you need them.
Now the first access, you see here in the bootloader.
You have the remote mounted, the remote file system.
And it's the implementation in barbox.
It's read right.
You can write to it if you have something.
You can also read from it.
I'm going to read now's bootloader spec file.
This describes how to boot the system.
I have a kernel.
I have a device tree.
I have an inner trauma fs, which is the RS in it.
I talked about and it has this extension Linux abandoned route through.
This tells barbox, please compute a convenient or matching route
command line argument for Linux.
You can see it now.
9p0 is our device.
This is what barbox compute would be the correct route argument to pass to Linux.
And when you normally boot, you don't need all of that.
It's an auto mount and everything is automatic.
So the only thing you need is to just type boot and then the path.
And it will do the bootloader spec stuff to find out what's the kernel,
what's the inner trauma fs and it will just boot.
So bootloader spec is what system deboot for example,
which is a fedora patched graph.
And so on, you see here that it talks a command line.
That barbox computed.
You see here the inner test started.
There are some not-so-nice warnings.
I hope to remove this here, finally.
Then here the system has booted.
Normally you have a lot of system d errors here,
because system decamp files,
they want to be happy about you ID not matching and so on.
But here it's only one of them.
I didn't have enough time to fix before the talk.
I don't understand it.
I am passing a machine ID.
So I am not sure why it says it can commit a transient machine ID.
But everything is working.
So it's my P as route fs type.
It's has transmission USBG.
And yeah, you can now on your remote system do an on your development host,
do stuff like bootback, something and see it appear here.
Or you can run s-trays and it's will end up in your remote system.
There is also an NFS CP helper that allows you to copy stuff while observing
the pseudo limitations or pseudo requirements.
Here is an example.
This is for means it's a suede binary and you ID zero g ID zero.
These are the stuff that normally breaks.
If you were to run your NFS day or diet without any fake route around it.
You would end up with your user ID or you have to use pseudo for extraction,
which is not really viable.
And yeah, that's the demo.
No.
Okay, thank you.
Thank you.
But I'm not done yet.
I don't.
Yeah.
It gets a bug.
Yeah.
I don't want you to think everything is done.
So it's the right to do.
So in bear box, I need to upstream the support.
I think I might get around to it this week.
In Linux, we have a limitation of only one inflight request.
You could increase that.
So as some robustness issues, like with rest conditions,
very early on that we need to fix.
Boot config might be a really nice idea to be able to set up gadgets
without using config fs.
We need to try that out.
Our S in it.
We want to package for this.
And maybe merge boot splash functionality into it.
So it's real.
So it's army knife.
Like our inner drum Fs needs open embedded core.
So yeah, it would be cool to contribute to stuff.
I talked about and we would also need a diagnosis.
A recipe.
But that should of course include my patches.
And these need to be cleaned up a bit.
So they are not nice at the moment.
P9 forward.
We could improve the detection of the gadget.
Currently it matches on vendor ID and product ID.
Which is not sufficient if you have like a multi gadget or want to use your custom stuff.
You can specify it.
But some more automation would be nice.
And same.
And I think with lab grid that might be some things that we will look into in the future.
So lab grid can provide you a fast boot resource.
For example.
And then you can say lab grid client.
Fast boot flash called a Python function to flash it.
And it would be nice if I could do the same thing.
Lab grid can do TCP forwarding over SSH.
So I could just tell it.
Hey, this has an IPFS port.
Please give it this diode instance.
Is that running here.
And then it would be just.
Yeah.
So it would be the most convenient way to use this I think.
But as it is already functional.
If you are interested, we have put up a GitHub repository.
And you can see our patches there.
And read me where we which we will update as we are going forward with upstreaming more stuff.
Yeah.
And that's it.
Now you can clap.
Sorry.
Any questions?
I think we have some time.
Yeah.
Three minutes.
Okay.
Thank you for your work.
I have been dressed in it.
And.
Okay.
Do think about standardization of the.
Nine BFS protocol over the USB because it would be big win against.
MTP and such horrible stuff.
Yeah.
As the other nine P product transmissions.
Standardized.
Okay.
Overall, I owe it's probably.
There is a better.
I respect.
But it's worth.
I owe it.
It really have a specification.
I'm not sure who I would even talk to to make this.
No, but to make it as a standard class for USB.
To standardization it for USB.
Okay.
Because it would be a win against MTP and all that horrible.
That's it's actually not the.
The way you think of because MTP is the other way around.
Because the gadget is exporting the file system.
Yeah.
And in our case, it's the other way around.
And I think about even the second way that it can be.
Standardized us.
Yeah.
But usually you don't want to expose your local file system to.
So you get it.
But anyway, to get an.
I identify for the USB class for it.
It's.
It's a good idea.
Probably.
So when you have.
Instability on the USB data connection.
You will will you have.
We will also mount a break.
So.
So if you have a short break on the data.
Line for a second.
Maybe.
So your.
Will your mount be lost or.
There's something recover.
And now it's.
It's currently it's recoverable.
And in the beginning, when the.
We have a current race when the.
Get it is exporting itself.
But the mount layer did not.
It's a client layer did not.
Created device.
It's a short gap.
So we we have to wait for some seconds.
But this will be fixable.
It's only that.
Short moment.
Okay.
Other than Linux fix system.
So I thought I thought this could be also useful.
For example debugging.
Pips and filter with networking problems.
Do you have any intentions to.
Add the USB 9 PFS support to the previous day.
Backpotting him in to previous.
Yes.
Well, yeah.
To other corners.
No, I don't.
I don't know.
Not we did not think about it yet.
Okay.
I just thought that this could be really useful.
Yeah.
So at least in.
At least in Linux.
It's pretty nicely abstracted.
It's.
And you have like multiple transmit transport modules.
So it's was.
It's it's really super easy to add to Linux.
Of course.
After fixing all bugs.
So if you're he cann� does a similar.
Separation might be easy to add or easy.
Add them doing suit from scratch.
Okay, so that's it.
Thank you for listening.
Thank you.