한 메모리 영역에 동시에 접근하는 문제...
글쓴이: cjy1126 / 작성시간: 목, 2004/02/05 - 1:13오후
제가 만들고 있는 swtich에 NIDS가 3개 붙어있습니다
라운드로빈같은 스켈쥴링 기법을 이용하여 NIDS에 패킷을 흘려보내는데, 같은 source ip에서 온 패킷은 계속 같은 곳으로 보내기위해서 테이블을 만들었습니다.(패킷분할공격대비용)
struct packet { struct list_head hash_list; u32 source; u32 dest; struct timer_list timer; struct net_device *dev; }
버킷의수가 4096개인 해쉬테이블을 만들어서 패킷이 올때마다 source ip와 dest ip로 해쉬값을 뽑아 그 패킷에대한 리스트가 있는지 search하고 있으면 그 패킷이 나갔던 *dev를 반환하고, 없으면packet 구조체형 링크드 리스트로 연결합니다.
오랬동안 사용안하는 리스트를 지우기위해서 add될때는 add_timer를 호출해서 (jiffies+60*HZ)을 timer의 expires로 설정하고, 호출함수는 delete_node를 호출합니다.
모듈로 테스트해봐서 여기까지는 잘 작동합니다.
문제는 실제 커널에 심었을때 expires가 지나면 delete_node를 호출하는데, 커널 패닉이 일어납니다.
제 생각으로는 네트웍 카드로 패킷은 계속 들어오는데, 60초가 지난 패킷이 지워짐과 동시에 들어오는것 같습니다.
즉... 같은 링크드 리스트의 구조체를 동시에 읽고 쓰는것 같습니다.
이 문제를 어떻게 해결해야하나요?
ipvs에 write_lock를 써도... 조금 더 버틸뿐이고... 결국은 커널패닉이 일어나네요.
Forums:
[quote]문제는 실제 커널에 심었을때 expires가 지나면 dele
만일 문제가 delete_node() 에서 발생하는 것이 맞다면,
그리고 지우려는 노드를 사용하려는 패킷이 접근을 하다가 panic이 발생하는
것이라면, 앞 부분에 버퍼를 두고 그곳에서 packet 노드를 접근하기 전에
그 노드가 존재하는지에 대한 체크를 하는 루틴을 넣어 보시는 것은 어떨까요?
존재하지 않는다면 그 버퍼에서 drop을 시켜 주는 방식이지요.
패킷처리루틴에 그렇게 많은 overhead를 줄거 같지는 않을거 같습니다. ^^
이미 해제된 메모리에 접근을 하게 되는게 아닌지..참조 방식으로 고쳐 보
이미 해제된 메모리에 접근을 하게 되는게 아닌지..참조 방식으로 고쳐 보시는건 어떠 실런지요..
리스트에 들어가는 데이터들에게 참조 카운터를 넣으셔서, 그 데이터를 사용하기 전에 참조 카운터를 증가 시키시고 사용 후에는 참조 카운터를 감소 시키주고, 참조 카운터가 0이 되면 메모리 반납을 해주는..그런 방식이요.
흐음...
답변 감사합니다.
문제는 kmalloc였네요.
처음에 해쉬 테이블을 만들때는 kmalloc로 할당하는게 맞는데, 패킷이 올때마다 할당받는 메모리는 작은 용량이라서 kmalloc로 할당하면 안된다더군요.
집에서 샤워하고 오는동안 같이 프로젝트하는분이 해결해놓으셨네요.
Re: 답변 감사합니다.
그럼 조그만 메모리를 관리하는 메모리관리자를 사용자가 작성해야 하는건가요? 어떻게 해결하셨는지 궁금.. ^^
제가 사용한 방법은
kmem_cache_create
kmem_cache_alloc
kmem_cache_free
kmem_cache_destroy
를 사용했습니다.
댓글 달기