Skip to content

Relax restriction of arbitration ID uniqueness for SocketCAN #785

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 11 commits into from
Apr 9, 2020

Conversation

tysonite
Copy link
Contributor

@tysonite tysonite commented Mar 2, 2020

References #721
I am unsure about the correct way to make a unique identifier. Please, suggest.

@codecov
Copy link

codecov bot commented Mar 2, 2020

Codecov Report

Merging #785 into develop will increase coverage by 0.07%.
The diff coverage is 95.23%.

@@             Coverage Diff             @@
##           develop     #785      +/-   ##
===========================================
+ Coverage    69.50%   69.58%   +0.07%     
===========================================
  Files           70       70              
  Lines         6556     6565       +9     
===========================================
+ Hits          4557     4568      +11     
+ Misses        1999     1997       -2     

Comment on lines 290 to 291
GLOBAL_TASK_ID = 0
TASK_LOCK = threading.Lock()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of making this global, perhaps consider storing this on the Bus context since we map 1:1 to a SocketCAN bus. This is because the kernel code matches based on the combination of:

  1. Task ID (op->can_id)
  2. Interface (op->ifindex)
  3. Flags (op->flags)
/*
 * helpers for bcm_op handling: find & delete bcm [rx|tx] op elements
 */
static struct bcm_op *bcm_find_op(struct list_head *ops,
				  struct bcm_msg_head *mh, int ifindex)
{
	struct bcm_op *op;

	list_for_each_entry(op, ops, list) {
		if ((op->can_id == mh->can_id) && (op->ifindex == ifindex) &&
		    (op->flags & CAN_FD_FRAME) == (mh->flags & CAN_FD_FRAME))
			return op;
	}

	return NULL;
}

(Taken from the 5.5.7 kernel)

I think this should be doable if we expand the socketcan.CyclicTask to take an ID argument in __init__. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. I am thinking about adding a member function to SocketcanBus class that returns next task ID, incrementing old one. The result of that function passed to CyclicSendTask::__init__ as an additional argument. I will try that.

Comment on lines 295 to 298
with TASK_LOCK:
global GLOBAL_TASK_ID
GLOBAL_TASK_ID += 1
return GLOBAL_TASK_ID
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will want to also ensure that we don't overflow the canid_t type, on the off-chance that someone is running this for extended periods of time and repeatedly starting/stopping periodic TX tasks.

typedef __u32 canid_t;

Ensuring that we wrap at 2^11 - 1 is probably sufficient for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, good catch. It looks to be an unsigned integer though, thus wrapping is required at 2^32 - 1, isn't it?

Considering this accidental case, some of the previous tasks IDs can be used already, wouldn't it better still implement usage of CAN_BCM_TX_READ to check if they are busy or not?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I commented, I wasn't sure if the kernel code was doing anything with anything beyond the 11-bits (ie. checking other bits for various flags in the 32-bits) so I just said 11-bits to be safe to avoid any potential unintended side effects.

Looking more closely through the kernel code now, it seems like for TX Tasks, this value is only copied (for things other than the TX Task ID) when TX_CP_CAN_ID is set as part of flags on the BCM message. The only places it's used for determining behaviour is when dealing with RX tasks, but they're stored in separate lists so they won't affect each other (and python-can currently doesn't support this).

But yes, you're right, it should be safe to increase this to 32-bits.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering this accidental case, some of the previous tasks IDs can be used already, wouldn't it better still implement usage of CAN_BCM_TX_READ to check if they are busy or not?

Yes, let's do that. If we detect that the TX ID has been used, let's just raise an Exception, and make it explicit for the user to decide whether to retry calling bus.send_periodic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


# The second one raises a ValueError when we attempt to create a new
# Task, since it has the same arbitration ID.
with self.assertRaises(ValueError):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this test could probably be repurposed to ensure that we receive both messages, rather than throwing an exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified this test.

@tysonite tysonite requested a review from karlding March 9, 2020 20:18
return task

def _get_next_task_id(self) -> int:
self._task_id = (self._task_id + 1) % (2 ** 11 - 1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you still need mutual exclusion around the task_id since access to the Bus via send_periodic isn't serialized. I think we assume that send_periodic can be called concurrently.

Copy link
Contributor Author

@tysonite tysonite Apr 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not really sure in that. There is ThreadSafeBus, but I don't really understand whether it serializes access to periodic messages sending. Anyway, I've added a guard.

@tysonite tysonite requested a review from karlding April 4, 2020 13:32
Copy link
Collaborator

@karlding karlding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM % the missing documentation comment. Thanks for working on this!

Copy link
Owner

@hardbyte hardbyte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking really solid. 🚀

Do you mind updating the interfaces/socketcan and bcm documentation too?

@tysonite
Copy link
Contributor Author

tysonite commented Apr 8, 2020

I thought about that too. No problem.

I would be happy to update if you point out what you want to add into existing documentation. Note please that those changes are not user-visible, public API hasn't changed.

But I could add some description that clarifies internals, though. Is that what you want?

@hardbyte
Copy link
Owner

hardbyte commented Apr 9, 2020

Awesome thanks, clarifying the internal behavior is what I was thinking. But you are now in the best position to check that the docstrings are still accurate e.g. socketcan.CyclicSendTask.

@tysonite
Copy link
Contributor Author

tysonite commented Apr 9, 2020

I did few more changes to Sphinx docs if you don't mind along with other updates to docstrings.

Copy link
Owner

@hardbyte hardbyte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌟 for extra doc updates. Thank you for improving python-can!

@hardbyte hardbyte merged commit 2d672b3 into hardbyte:develop Apr 9, 2020
@tysonite
Copy link
Contributor Author

@karlding, @hardbyte, thank you for review and letting that in.

@tysonite tysonite deleted the equal_arbids branch April 18, 2020 13:49
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants